refactor passage of ex-global class instances

This commit is contained in:
Holly Stubbs 2022-11-19 22:28:46 +00:00
parent 3da964f5d6
commit f7f2df1287
Signed by: tgpholly
GPG key ID: B8583C4B7D18119E
8 changed files with 45 additions and 42 deletions

View file

@ -11,14 +11,14 @@ if (!existsSync("./config.json")) {
import { ChatHistory } from "./server/ChatHistory"; import { ChatHistory } from "./server/ChatHistory";
import compression from "compression"; import compression from "compression";
import express from "express"; import express from "express";
import { HandleRequest } from "./server/BanchoServer"; import { HandleRequest, GetSharedContent, SharedContent } from "./server/BanchoServer";
import { Registry, collectDefaultMetrics } from "prom-client"; import { Registry, collectDefaultMetrics } from "prom-client";
const config:any = JSON.parse(readFileSync(__dirname + "/config.json").toString()); const config:any = JSON.parse(readFileSync(__dirname + "/config.json").toString());
// Pull out shared data from BanchoServer
const sharedContent:SharedContent = GetSharedContent();
const binatoApp:express.Application = express(); const binatoApp:express.Application = express();
ConsoleHelper.printInfo("Starting Binato...");
if (config["prometheus"]["enabled"]) { if (config["prometheus"]["enabled"]) {
const register:Registry = new Registry(); const register:Registry = new Registry();
register.setDefaultLabels({ app: "nodejs_binato" }); register.setDefaultLabels({ app: "nodejs_binato" });

View file

@ -17,29 +17,43 @@ const config:any = JSON.parse(readFileSync("./config.json").toString());
// TODO: Port osu-packet to TypeScript // TODO: Port osu-packet to TypeScript
const osu = require("osu-packet"); const osu = require("osu-packet");
const DB:Database = new Database(config.database.address, config.database.port, config.database.username, config.database.password, config.database.name, async () => { export interface SharedContent {
chatManager:ChatManager,
database:Database,
mutiplayerManager:MultiplayerManager,
streams:DataStreamArray,
users:UserArray,
}
const sharedContent:any = {};
// NOTE: This function should only be used externaly in Binato.ts and in this file.
export function GetSharedContent() : SharedContent {
return sharedContent;
}
const DB:Database = sharedContent.database = new Database(config.database.address, config.database.port, config.database.username, config.database.password, config.database.name, async () => {
// Close any unclosed db matches on startup // Close any unclosed db matches on startup
DB.query("UPDATE mp_matches SET close_time = UNIX_TIMESTAMP() WHERE close_time IS NULL"); DB.query("UPDATE mp_matches SET close_time = UNIX_TIMESTAMP() WHERE close_time IS NULL");
DB.query("UPDATE osu_info SET value = 0 WHERE name = 'online_now'"); DB.query("UPDATE osu_info SET value = 0 WHERE name = 'online_now'");
}); });
// User session storage // User session storage
const users:UserArray = new UserArray(); const users:UserArray = sharedContent.users = new UserArray();
// DataStream storage // DataStream storage
const streams:DataStreamArray = new DataStreamArray(); const streams:DataStreamArray = sharedContent.streams = new DataStreamArray();
// ChatManager // ChatManager
const chatManager:ChatManager = new ChatManager(streams); const chatManager:ChatManager = sharedContent.chatManager = new ChatManager(streams);
chatManager.AddChatChannel("osu", "The main channel", true); chatManager.AddChatChannel("osu", "The main channel", true);
chatManager.AddChatChannel("lobby", "Talk about multiplayer stuff"); chatManager.AddChatChannel("lobby", "Talk about multiplayer stuff");
chatManager.AddChatChannel("english", "Talk in exclusively English"); chatManager.AddChatChannel("english", "Talk in exclusively English");
chatManager.AddChatChannel("japanese", "Talk in exclusively Japanese"); chatManager.AddChatChannel("japanese", "Talk in exclusively Japanese");
const multiplayerManager:MultiplayerManager = new MultiplayerManager(streams); const multiplayerManager:MultiplayerManager = sharedContent.mutiplayerManager = new MultiplayerManager(streams);
// Add the bot user // Add the bot user
const botUser:User = users.add("bot", new User(3, "SillyBot", "bot", DB, users, streams, chatManager)); const botUser:User = users.add("bot", new User(3, "SillyBot", "bot", GetSharedContent()));
// Set the bot's position on the map // Set the bot's position on the map
botUser.location = new LatLng(50, -32); botUser.location = new LatLng(50, -32);
@ -116,7 +130,7 @@ export async function HandleRequest(req:Request, res:Response, packet:Buffer) {
if (DB.connected) { if (DB.connected) {
// Client doesn't have a token yet, let's auth them! // Client doesn't have a token yet, let's auth them!
await LoginProcess(req, res, packet, DB, users, streams, chatManager); await LoginProcess(req, res, packet, GetSharedContent());
DB.query("UPDATE osu_info SET value = ? WHERE name = 'online_now'", [users.getLength() - 1]); DB.query("UPDATE osu_info SET value = ? WHERE name = 'online_now'", [users.getLength() - 1]);
} }
} else { } else {

View file

@ -16,6 +16,7 @@ import { ChatManager } from "./ChatManager";
import { UserPresenceBundle } from "./packets/UserPresenceBundle"; import { UserPresenceBundle } from "./packets/UserPresenceBundle";
import { UserPresence } from "./packets/UserPresence"; import { UserPresence } from "./packets/UserPresence";
import { StatusUpdate } from "./packets/StatusUpdate"; import { StatusUpdate } from "./packets/StatusUpdate";
import { SharedContent } from "./BanchoServer";
const config:any = JSON.parse(readFileSync("./config.json").toString()); const config:any = JSON.parse(readFileSync("./config.json").toString());
const { decrypt: aesDecrypt } = require("aes256"); const { decrypt: aesDecrypt } = require("aes256");
const osu = require("osu-packet"); const osu = require("osu-packet");
@ -95,11 +96,11 @@ function TestLogin(loginInfo:LoginInfo | undefined, database:Database) {
}); });
} }
export async function LoginProcess(req:Request, res:Response, packet:Buffer, database:Database, users:UserArray, streams:DataStreamArray, chatManager:ChatManager) { export async function LoginProcess(req:Request, res:Response, packet:Buffer, sharedContent:SharedContent) {
const loginInfo = LoginInfo.From(packet); const loginInfo = LoginInfo.From(packet);
const loginStartTime = Date.now(); const loginStartTime = Date.now();
const loginCheck:any = await TestLogin(loginInfo, database); const loginCheck:any = await TestLogin(loginInfo, sharedContent.database);
if (loginCheck != null) { if (loginCheck != null) {
res.writeHead(200, loginCheck[1]); res.writeHead(200, loginCheck[1]);
return res.end(loginCheck[0]); return res.end(loginCheck[0]);
@ -143,20 +144,20 @@ export async function LoginProcess(req:Request, res:Response, packet:Buffer, dat
} }
// Get information about the user from the database // Get information about the user from the database
const userDB = await database.query("SELECT id FROM users_info WHERE username = ? LIMIT 1", [loginInfo.username]); const userDB = await sharedContent.database.query("SELECT id FROM users_info WHERE username = ? LIMIT 1", [loginInfo.username]);
// Create a token for the client // Create a token for the client
const newClientToken:string = await generateSession(); const newClientToken:string = await generateSession();
const isTourneyClient = loginInfo.version.includes("tourney"); const isTourneyClient = loginInfo.version.includes("tourney");
// Make sure user is not already connected, kick off if so. // Make sure user is not already connected, kick off if so.
const connectedUser = users.getByUsername(loginInfo.username); const connectedUser = sharedContent.users.getByUsername(loginInfo.username);
if (connectedUser != null && !isTourneyClient && !connectedUser.isTourneyUser) { if (connectedUser != null && !isTourneyClient && !connectedUser.isTourneyUser) {
Logout(connectedUser); Logout(connectedUser);
} }
// Retreive the newly created user // Retreive the newly created user
const newUser:User = users.add(newClientToken, new User(userDB.id, loginInfo.username, newClientToken, database, users, streams, chatManager)); const newUser:User = sharedContent.users.add(newClientToken, new User(userDB.id, loginInfo.username, newClientToken, sharedContent));
// Set tourney client flag // Set tourney client flag
newUser.isTourneyUser = isTourneyClient; newUser.isTourneyUser = isTourneyClient;
newUser.location = userLocation; newUser.location = userLocation;
@ -193,11 +194,11 @@ export async function LoginProcess(req:Request, res:Response, packet:Buffer, dat
osuPacketWriter.ChannelListingComplete(); osuPacketWriter.ChannelListingComplete();
// Setup chat // Setup chat
chatManager.ForceJoinChannels(newUser); sharedContent.chatManager.ForceJoinChannels(newUser);
chatManager.SendChannelListing(newUser); sharedContent.chatManager.SendChannelListing(newUser);
// Construct user's friends list // Construct user's friends list
const userFriends = await database.query("SELECT friendsWith FROM friends WHERE user = ?", [newUser.id]); const userFriends = await sharedContent.database.query("SELECT friendsWith FROM friends WHERE user = ?", [newUser.id]);
const friendsArray:Array<number> = new Array<number>(); const friendsArray:Array<number> = new Array<number>();
for (let i = 0; i < userFriends.length; i++) { for (let i = 0; i < userFriends.length; i++) {
friendsArray.push(userFriends[i].friendsWith); friendsArray.push(userFriends[i].friendsWith);

View file

@ -1,13 +1,9 @@
import { Database } from "./Database";
import { LatLng } from "./LatLng"; import { LatLng } from "./LatLng";
import { RankingModes } from "../enums/RankingModes"; import { RankingModes } from "../enums/RankingModes";
import { Match } from "./Match"; import { Match } from "./Match";
import { DataStream } from "./DataStream"; import { DataStream } from "./DataStream";
import { UserArray } from "./UserArray";
import { DataStreamArray } from "./DataStreamArray";
import { ChatManager } from "../ChatManager";
import { StatusUpdate } from "../packets/StatusUpdate"; import { StatusUpdate } from "../packets/StatusUpdate";
//const StatusUpdate = require("./Packets/StatusUpdate.js"); import { SharedContent } from "../BanchoServer";
const rankingModes = [ const rankingModes = [
"pp_raw", "pp_raw",
@ -18,9 +14,7 @@ const rankingModes = [
export class User { export class User {
private static readonly EMPTY_BUFFER = Buffer.alloc(0); private static readonly EMPTY_BUFFER = Buffer.alloc(0);
public users:UserArray; public sharedContent:SharedContent;
public streams:DataStreamArray;
public chatManager:ChatManager;
public id:number; public id:number;
public username:string; public username:string;
@ -65,18 +59,12 @@ export class User {
// Tournament client flag // Tournament client flag
public isTourneyUser:boolean = false; public isTourneyUser:boolean = false;
public dbConnection:Database; public constructor(id:number, username:string, uuid:string, sharedContent:SharedContent) {
public constructor(id:number, username:string, uuid:string, dbConnection:Database, users:UserArray, streams:DataStreamArray, chatManager:ChatManager) {
this.id = id; this.id = id;
this.username = username; this.username = username;
this.uuid = uuid; this.uuid = uuid;
this.dbConnection = dbConnection; this.sharedContent = sharedContent;
this.users = users;
this.streams = streams;
this.chatManager = chatManager;
} }
// Concats new actions to the user's queue // Concats new actions to the user's queue
@ -104,9 +92,9 @@ export class User {
// Gets the user's score information from the database and caches it // Gets the user's score information from the database and caches it
async updateUserInfo(forceUpdate:boolean = false) : Promise<void> { async updateUserInfo(forceUpdate:boolean = false) : Promise<void> {
const userScoreDB = await this.dbConnection.query("SELECT * FROM users_modes_info WHERE user_id = ? AND mode_id = ? LIMIT 1", [this.id, this.playMode]); const userScoreDB = await this.sharedContent.database.query("SELECT * FROM users_modes_info WHERE user_id = ? AND mode_id = ? LIMIT 1", [this.id, this.playMode]);
const mappedRankingMode = rankingModes[this.rankingMode]; const mappedRankingMode = rankingModes[this.rankingMode];
const userRankDB = await this.dbConnection.query(`SELECT user_id, ${mappedRankingMode} FROM users_modes_info WHERE mode_id = ? ORDER BY ${mappedRankingMode} DESC`, [this.playMode]); const userRankDB = await this.sharedContent.database.query(`SELECT user_id, ${mappedRankingMode} FROM users_modes_info WHERE mode_id = ? ORDER BY ${mappedRankingMode} DESC`, [this.playMode]);
if (userScoreDB == null || userRankDB == null) throw "fuck"; if (userScoreDB == null || userRankDB == null) throw "fuck";

View file

@ -8,12 +8,12 @@ export async function Logout(user:User) {
const logoutStartTime = Date.now(); const logoutStartTime = Date.now();
user.streams.RemoveUserFromAllStreams(user); user.sharedContent.streams.RemoveUserFromAllStreams(user);
// Remove user from user list // Remove user from user list
user.users.remove(user.uuid); user.sharedContent.users.remove(user.uuid);
await user.dbConnection.query("UPDATE osu_info SET value = ? WHERE name = 'online_now'", [user.users.getLength() - 1]); await user.sharedContent.database.query("UPDATE osu_info SET value = ? WHERE name = 'online_now'", [user.sharedContent.users.getLength() - 1]);
ConsoleHelper.printBancho(`User logged out, took ${Date.now() - logoutStartTime}ms. [User: ${user.username}]`); ConsoleHelper.printBancho(`User logged out, took ${Date.now() - logoutStartTime}ms. [User: ${user.username}]`);
} }

View file

@ -9,7 +9,7 @@ export function StatusUpdate(user:User, id:number, sendImmidiate:boolean = false
const osuPacketWriter = new osu.Bancho.Writer; const osuPacketWriter = new osu.Bancho.Writer;
// Get user's class // Get user's class
const userData = user.users.getById(id); const userData = user.sharedContent.users.getById(id);
if (userData == null) return; if (userData == null) return;

View file

@ -4,7 +4,7 @@ const osu = require("osu-packet");
export function UserPresence(user:User, id:number, sendImmidiate:boolean = true) { export function UserPresence(user:User, id:number, sendImmidiate:boolean = true) {
const osuPacketWriter = new osu.Bancho.Writer; const osuPacketWriter = new osu.Bancho.Writer;
const userData = user.users.getById(id); const userData = user.sharedContent.users.getById(id);
if (userData == null) return; if (userData == null) return;

View file

@ -6,7 +6,7 @@ export function UserPresenceBundle(user:User, sendImmidiate:boolean = true) {
let userIds:Array<number> = new Array<number>(); let userIds:Array<number> = new Array<number>();
for (let userData of user.users.getIterableItems()) { for (let userData of user.sharedContent.users.getIterableItems()) {
userIds.push(userData.id); userIds.push(userData.id);
} }