multiplayer

This commit is contained in:
Holly Stubbs 2022-11-20 23:37:39 +00:00
parent f7f2df1287
commit e297aa1128
Signed by: tgpholly
GPG key ID: B8583C4B7D18119E
9 changed files with 159 additions and 76 deletions

View file

@ -50,7 +50,7 @@ chatManager.AddChatChannel("lobby", "Talk about multiplayer stuff");
chatManager.AddChatChannel("english", "Talk in exclusively English");
chatManager.AddChatChannel("japanese", "Talk in exclusively Japanese");
const multiplayerManager:MultiplayerManager = sharedContent.mutiplayerManager = new MultiplayerManager(streams);
const multiplayerManager:MultiplayerManager = sharedContent.mutiplayerManager = new MultiplayerManager(GetSharedContent());
// Add the bot user
const botUser:User = users.add("bot", new User(3, "SillyBot", "bot", GetSharedContent()));
@ -198,7 +198,7 @@ export async function HandleRequest(req:Request, res:Response, packet:Buffer) {
break;
case Packets.Client_CreateMatch:
//await multiplayerManager.createMultiplayerMatch(PacketUser, CurrentPacket.data);
await multiplayerManager.CreateMatch(PacketUser, CurrentPacket.data);
break;
case Packets.Client_JoinMatch:

View file

@ -14,7 +14,7 @@ export class ChatManager {
this.streams = streams;
}
public AddChatChannel(name:string, description:string, forceJoin:boolean = false) {
public AddChatChannel(name:string, description:string, forceJoin:boolean = false) : Channel {
const stream = this.streams.CreateStream(`chat_channel:${name}`, false);
const channel = new Channel(`#${name}`, description, stream);
this.chatChannels.add(channel.name, channel);
@ -22,6 +22,18 @@ export class ChatManager {
this.forceJoinChannels.add(name, channel);
}
ConsoleHelper.printChat(`Created chat channel [${name}]`);
return channel;
}
public AddSpecialChatChannel(name:string, streamName:string, forceJoin:boolean = false) : Channel {
const stream = this.streams.CreateStream(`chat_channel:${streamName}`, false);
const channel = new Channel(`#${name}`, "", stream);
this.chatChannels.add(channel.name, channel);
if (forceJoin) {
this.forceJoinChannels.add(name, channel);
}
ConsoleHelper.printChat(`Created chat channel [${name}]`);
return channel;
}
public RemoveChatChannel(channel:Channel | string) {
@ -52,6 +64,10 @@ export class ChatManager {
public SendChannelListing(user:User) {
const osuPacketWriter = new osu.Bancho.Writer;
for (let channel of this.chatChannels.getIterableItems()) {
if (channel.isSpecial) {
continue;
}
osuPacketWriter.ChannelAvailable({
channelName: channel.name,
channelTopic: channel.description,

View file

@ -1,15 +1,18 @@
import { SharedContent } from "./BanchoServer";
import { DataStream } from "./objects/DataStream";
import { DataStreamArray } from "./objects/DataStreamArray";
import { FunkyArray } from "./objects/FunkyArray";
import { Match } from "./objects/Match";
import { Match, MatchData } from "./objects/Match";
import { User } from "./objects/User";
export class MultiplayerManager {
private readonly sharedContent:SharedContent;
private matches:FunkyArray<Match> = new FunkyArray<Match>();
private readonly lobbyStream:DataStream;
public constructor(streams:DataStreamArray) {
this.lobbyStream = streams.CreateStream("multiplayer:lobby", false);
public constructor(sharedContent:SharedContent) {
this.sharedContent = sharedContent;
this.lobbyStream = sharedContent.streams.CreateStream("multiplayer:lobby", false);
}
public JoinLobby(user:User) {
@ -17,4 +20,9 @@ export class MultiplayerManager {
}
}
public async CreateMatch(user:User, matchData:MatchData) {
const match = await Match.createMatch(user, matchData, this.sharedContent);
this.matches.add(match.matchId.toString(), match);
}
}

View file

@ -38,3 +38,11 @@ export function hexlify(data:Buffer) : string {
return out.slice(0, out.length - 1);
}
export function isNullOrEmpty(str:string | undefined | null) {
if (typeof(str) === "string") {
return str !== "";
}
return false;
}

3
server/enums/Mods.ts Normal file
View file

@ -0,0 +1,3 @@
export enum Mods {
}

View file

@ -7,11 +7,17 @@ export class Channel {
public description:string;
public stream:DataStream;
private isLocked:boolean = false;
private _isSpecial:boolean = false;
public constructor(name:string, description:string, stream:DataStream) {
public constructor(name:string, description:string, stream:DataStream, isSpecial:boolean = false) {
this.name = name;
this.description = description;
this.stream = stream;
this._isSpecial = isSpecial;
}
public get isSpecial() {
return this._isSpecial;
}
public get userCount() {

View file

@ -1,16 +1,43 @@
import { Channel } from "./Channel";
import { SharedContent } from "../BanchoServer";
import { DataStream } from "./DataStream";
import { Slot } from "./Slot";
import { User } from "./User";
import { StatusUpdate } from "../packets/StatusUpdate";
const osu = require("osu-packet");
export interface MatchData {
matchId:number,
matchType:number,
activeMods:number,
gameName:string,
gamePassword:string,
inProgress:boolean,
beatmapName:string,
beatmapId:number,
beatmapChecksum:string,
slots:Array<any>,
host:number,
playMode:number,
matchScoringType:number,
matchTeamType:number,
specialModes:number,
seed:number
}
export class Match {
/*public matchId:number = -1;
// osu! Data
public matchId:number = -1;
public inProgress:boolean = false;
public matchType: 0;
public activeMods: 0;
public gameName: "";
public gamePassword: '';
public beatmapName: '';
public beatmapId: 0;
public beatmapChecksum: '';
public slots: [];
public matchType:number = 0;
public activeMods:number = 0;
public gameName:string = "";
public gamePassword:string | undefined = '';
public beatmapName:string = '';
public beatmapId:number = 0;
public beatmapChecksum:string = '';
public slots:Array<Slot> = new Array<Slot>();
public host:number = 0;
public playMode:number = 0;
public matchScoringType:number = 0;
@ -18,86 +45,91 @@ export class Match {
public specialModes:number = 0;
public seed:number = 0;
constructor(MatchData = {}) {
this.matchId = MatchData.matchId;
// Binato data
public roundId:number = 0;
public matchStartCountdownActive:boolean = false;
public matchStream:DataStream;
public matchChatChannel:Channel;
this.roundId = 0;
private constructor(matchData:MatchData, sharedContent:SharedContent) {
console.log(matchData);
this.matchId = matchData.matchId;
this.inProgress = MatchData.inProgress;
this.matchStartCountdownActive = false;
this.inProgress = matchData.inProgress;
this.matchType = MatchData.matchType;
this.matchType = matchData.matchType;
this.activeMods = MatchData.activeMods;
this.activeMods = matchData.activeMods;
this.gameName = MatchData.gameName;
if (MatchData.gamePassword == '') MatchData.gamePassword == null;
this.gamePassword = MatchData.gamePassword;
this.gameName = matchData.gameName;
if (matchData.gamePassword == '') matchData.gamePassword == null;
this.gamePassword = matchData.gamePassword;
this.beatmapName = MatchData.beatmapName;
this.beatmapId = MatchData.beatmapId;
this.beatmapChecksum = MatchData.beatmapChecksum;
this.beatmapName = matchData.beatmapName;
this.beatmapId = matchData.beatmapId;
this.beatmapChecksum = matchData.beatmapChecksum;
this.slots = MatchData.slots;
this.slots = matchData.slots;
for (let i = 0; i < this.slots.length; i++) {
this.slots[i].mods = 0;
//this.slots[i].mods = 0;
}
this.host = MatchData.host;
this.host = matchData.host;
this.playMode = MatchData.playMode;
this.playMode = matchData.playMode;
this.matchScoringType = MatchData.matchScoringType;
this.matchTeamType = MatchData.matchTeamType;
this.specialModes = MatchData.specialModes;
this.matchScoringType = matchData.matchScoringType;
this.matchTeamType = matchData.matchTeamType;
this.specialModes = matchData.specialModes;
this.seed = MatchData.seed;
this.seed = matchData.seed;
this.matchStreamName = `mp_${this.matchId}`;
this.matchChatStreamName = `mp_chat_${this.matchId}`;
this.matchStream = sharedContent.streams.CreateStream(`multiplayer:match_${this.matchId}`);
this.matchChatChannel = sharedContent.chatManager.AddSpecialChatChannel("multiplayer", `mp_${this.matchId}`);
this.matchLoadSlots = null;
this.matchSkippedSlots = null;
//this.matchLoadSlots = null;
//this.matchSkippedSlots = null;
this.playerScores = null;
//this.playerScores = null;
this.multiplayerExtras = null;
//this.multiplayerExtras = null;
this.isTourneyMatch = false;
this.tourneyClientUsers = [];
//this.isTourneyMatch = false;
//this.tourneyClientUsers = [];
}
static createMatch(MatchHost = new User, MatchData = {matchId: -1,inProgress: false,matchType: 0,activeMods: 0,gameName: "",gamePassword: '',beatmapName: '',beatmapId: 0,beatmapChecksum: '',slots: [],host: 0,playMode: 0,matchScoringType: 0,matchTeamType: 0,specialModes: 0,seed: 0}) {
return new Promise(async (resolve, reject) => {
MatchData.matchId = (await global.DatabaseHelper.query(
public static createMatch(matchHost:User, matchData:MatchData, sharedContent:SharedContent) : Promise<Match> {
return new Promise<Match>(async (resolve, reject) => {
try {
matchData.matchId = (await sharedContent.database.query(
"INSERT INTO mp_matches (id, name, open_time, close_time, seed) VALUES (NULL, ?, UNIX_TIMESTAMP(), NULL, ?) RETURNING id;",
[MatchData.gameName, MatchData.seed]
[matchData.gameName, matchData.seed]
))[0]["id"];
const matchInstance = new MultiplayerMatch(MatchData);
const matchInstance = new Match(matchData, sharedContent);
console.log(matchInstance.matchId);
// Update the status of the current user
StatusUpdate(MatchHost, MatchHost.id);
StatusUpdate(matchHost, matchHost.id);
const osuPacketWriter = new osu.Bancho.Writer;
osuPacketWriter.MatchNew(matchInstance.createOsuMatchJSON());
//osuPacketWriter.MatchNew(matchInstance.createOsuMatchJSON());
MatchHost.addActionToQueue(osuPacketWriter.toBuffer);
Streams.addStream(matchInstance.matchStreamName, true, matchInstance.matchId);
Streams.addStream(matchInstance.matchChatStreamName, true, matchInstance.matchId);
matchHost.addActionToQueue(osuPacketWriter.toBuffer);
// Update the match listing for users in the multiplayer lobby
global.MultiplayerManager.updateMatchListing();
//global.MultiplayerManager.updateMatchListing();
resolve(matchInstance);
} catch (e) {
reject(e);
}
});
}
getSlotIdByPlayerId(playerId = 0) {
/*getSlotIdByPlayerId(playerId = 0) {
const player = getUserById(playerId);
if (player != null) return player.matchSlotId;

View file

@ -1,3 +1,13 @@
export class Slot {
public status:number;
public team:number;
public player:number; // playerId
public mods:number;
public constructor() {
this.status = 0;
this.team = 0;
this.player = 0;
this.mods = 0;
}
}

View file

@ -2,7 +2,7 @@ import { RankingModes } from "../enums/RankingModes";
import { User } from "../objects/User";
const osu = require("osu-packet");
export function StatusUpdate(user:User, id:number, sendImmidiate:boolean = false) {
export function StatusUpdate(user:User, id:number, sendImmidiate:boolean = true) {
if (id == 3) return; // Ignore Bot
// Create new osu packet writer