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 compression from "compression";
import express from "express";
import { HandleRequest } from "./server/BanchoServer";
import { HandleRequest, GetSharedContent, SharedContent } from "./server/BanchoServer";
import { Registry, collectDefaultMetrics } from "prom-client";
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();
ConsoleHelper.printInfo("Starting Binato...");
if (config["prometheus"]["enabled"]) {
const register:Registry = new Registry();
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
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
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'");
});
// User session storage
const users:UserArray = new UserArray();
const users:UserArray = sharedContent.users = new UserArray();
// DataStream storage
const streams:DataStreamArray = new DataStreamArray();
const streams:DataStreamArray = sharedContent.streams = new DataStreamArray();
// ChatManager
const chatManager:ChatManager = new ChatManager(streams);
const chatManager:ChatManager = sharedContent.chatManager = new ChatManager(streams);
chatManager.AddChatChannel("osu", "The main channel", true);
chatManager.AddChatChannel("lobby", "Talk about multiplayer stuff");
chatManager.AddChatChannel("english", "Talk in exclusively English");
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
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
botUser.location = new LatLng(50, -32);
@ -116,7 +130,7 @@ export async function HandleRequest(req:Request, res:Response, packet:Buffer) {
if (DB.connected) {
// 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]);
}
} else {

View file

@ -16,6 +16,7 @@ import { ChatManager } from "./ChatManager";
import { UserPresenceBundle } from "./packets/UserPresenceBundle";
import { UserPresence } from "./packets/UserPresence";
import { StatusUpdate } from "./packets/StatusUpdate";
import { SharedContent } from "./BanchoServer";
const config:any = JSON.parse(readFileSync("./config.json").toString());
const { decrypt: aesDecrypt } = require("aes256");
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 loginStartTime = Date.now();
const loginCheck:any = await TestLogin(loginInfo, database);
const loginCheck:any = await TestLogin(loginInfo, sharedContent.database);
if (loginCheck != null) {
res.writeHead(200, loginCheck[1]);
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
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
const newClientToken:string = await generateSession();
const isTourneyClient = loginInfo.version.includes("tourney");
// 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) {
Logout(connectedUser);
}
// 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
newUser.isTourneyUser = isTourneyClient;
newUser.location = userLocation;
@ -193,11 +194,11 @@ export async function LoginProcess(req:Request, res:Response, packet:Buffer, dat
osuPacketWriter.ChannelListingComplete();
// Setup chat
chatManager.ForceJoinChannels(newUser);
chatManager.SendChannelListing(newUser);
sharedContent.chatManager.ForceJoinChannels(newUser);
sharedContent.chatManager.SendChannelListing(newUser);
// 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>();
for (let i = 0; i < userFriends.length; i++) {
friendsArray.push(userFriends[i].friendsWith);

View file

@ -1,13 +1,9 @@
import { Database } from "./Database";
import { LatLng } from "./LatLng";
import { RankingModes } from "../enums/RankingModes";
import { Match } from "./Match";
import { DataStream } from "./DataStream";
import { UserArray } from "./UserArray";
import { DataStreamArray } from "./DataStreamArray";
import { ChatManager } from "../ChatManager";
import { StatusUpdate } from "../packets/StatusUpdate";
//const StatusUpdate = require("./Packets/StatusUpdate.js");
import { SharedContent } from "../BanchoServer";
const rankingModes = [
"pp_raw",
@ -18,9 +14,7 @@ const rankingModes = [
export class User {
private static readonly EMPTY_BUFFER = Buffer.alloc(0);
public users:UserArray;
public streams:DataStreamArray;
public chatManager:ChatManager;
public sharedContent:SharedContent;
public id:number;
public username:string;
@ -65,18 +59,12 @@ export class User {
// Tournament client flag
public isTourneyUser:boolean = false;
public dbConnection:Database;
public constructor(id:number, username:string, uuid:string, dbConnection:Database, users:UserArray, streams:DataStreamArray, chatManager:ChatManager) {
public constructor(id:number, username:string, uuid:string, sharedContent:SharedContent) {
this.id = id;
this.username = username;
this.uuid = uuid;
this.dbConnection = dbConnection;
this.users = users;
this.streams = streams;
this.chatManager = chatManager;
this.sharedContent = sharedContent;
}
// 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
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 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";

View file

@ -8,12 +8,12 @@ export async function Logout(user:User) {
const logoutStartTime = Date.now();
user.streams.RemoveUserFromAllStreams(user);
user.sharedContent.streams.RemoveUserFromAllStreams(user);
// 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}]`);
}

View file

@ -9,7 +9,7 @@ export function StatusUpdate(user:User, id:number, sendImmidiate:boolean = false
const osuPacketWriter = new osu.Bancho.Writer;
// Get user's class
const userData = user.users.getById(id);
const userData = user.sharedContent.users.getById(id);
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) {
const osuPacketWriter = new osu.Bancho.Writer;
const userData = user.users.getById(id);
const userData = user.sharedContent.users.getById(id);
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>();
for (let userData of user.users.getIterableItems()) {
for (let userData of user.sharedContent.users.getIterableItems()) {
userIds.push(userData.id);
}