multiplayer
This commit is contained in:
parent
f7f2df1287
commit
e297aa1128
9 changed files with 159 additions and 76 deletions
|
@ -50,7 +50,7 @@ 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 = sharedContent.mutiplayerManager = new MultiplayerManager(streams);
|
const multiplayerManager:MultiplayerManager = sharedContent.mutiplayerManager = new MultiplayerManager(GetSharedContent());
|
||||||
|
|
||||||
// Add the bot user
|
// Add the bot user
|
||||||
const botUser:User = users.add("bot", new User(3, "SillyBot", "bot", GetSharedContent()));
|
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;
|
break;
|
||||||
|
|
||||||
case Packets.Client_CreateMatch:
|
case Packets.Client_CreateMatch:
|
||||||
//await multiplayerManager.createMultiplayerMatch(PacketUser, CurrentPacket.data);
|
await multiplayerManager.CreateMatch(PacketUser, CurrentPacket.data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Packets.Client_JoinMatch:
|
case Packets.Client_JoinMatch:
|
||||||
|
|
|
@ -14,7 +14,7 @@ export class ChatManager {
|
||||||
this.streams = streams;
|
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 stream = this.streams.CreateStream(`chat_channel:${name}`, false);
|
||||||
const channel = new Channel(`#${name}`, description, stream);
|
const channel = new Channel(`#${name}`, description, stream);
|
||||||
this.chatChannels.add(channel.name, channel);
|
this.chatChannels.add(channel.name, channel);
|
||||||
|
@ -22,6 +22,18 @@ export class ChatManager {
|
||||||
this.forceJoinChannels.add(name, channel);
|
this.forceJoinChannels.add(name, channel);
|
||||||
}
|
}
|
||||||
ConsoleHelper.printChat(`Created chat channel [${name}]`);
|
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) {
|
public RemoveChatChannel(channel:Channel | string) {
|
||||||
|
@ -52,6 +64,10 @@ export class ChatManager {
|
||||||
public SendChannelListing(user:User) {
|
public SendChannelListing(user:User) {
|
||||||
const osuPacketWriter = new osu.Bancho.Writer;
|
const osuPacketWriter = new osu.Bancho.Writer;
|
||||||
for (let channel of this.chatChannels.getIterableItems()) {
|
for (let channel of this.chatChannels.getIterableItems()) {
|
||||||
|
if (channel.isSpecial) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
osuPacketWriter.ChannelAvailable({
|
osuPacketWriter.ChannelAvailable({
|
||||||
channelName: channel.name,
|
channelName: channel.name,
|
||||||
channelTopic: channel.description,
|
channelTopic: channel.description,
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
|
import { SharedContent } from "./BanchoServer";
|
||||||
import { DataStream } from "./objects/DataStream";
|
import { DataStream } from "./objects/DataStream";
|
||||||
import { DataStreamArray } from "./objects/DataStreamArray";
|
import { DataStreamArray } from "./objects/DataStreamArray";
|
||||||
import { FunkyArray } from "./objects/FunkyArray";
|
import { FunkyArray } from "./objects/FunkyArray";
|
||||||
import { Match } from "./objects/Match";
|
import { Match, MatchData } from "./objects/Match";
|
||||||
import { User } from "./objects/User";
|
import { User } from "./objects/User";
|
||||||
|
|
||||||
export class MultiplayerManager {
|
export class MultiplayerManager {
|
||||||
|
private readonly sharedContent:SharedContent;
|
||||||
private matches:FunkyArray<Match> = new FunkyArray<Match>();
|
private matches:FunkyArray<Match> = new FunkyArray<Match>();
|
||||||
private readonly lobbyStream:DataStream;
|
private readonly lobbyStream:DataStream;
|
||||||
|
|
||||||
public constructor(streams:DataStreamArray) {
|
public constructor(sharedContent:SharedContent) {
|
||||||
this.lobbyStream = streams.CreateStream("multiplayer:lobby", false);
|
this.sharedContent = sharedContent;
|
||||||
|
this.lobbyStream = sharedContent.streams.CreateStream("multiplayer:lobby", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JoinLobby(user:User) {
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -38,3 +38,11 @@ export function hexlify(data:Buffer) : string {
|
||||||
|
|
||||||
return out.slice(0, out.length - 1);
|
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
3
server/enums/Mods.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export enum Mods {
|
||||||
|
|
||||||
|
}
|
|
@ -7,11 +7,17 @@ export class Channel {
|
||||||
public description:string;
|
public description:string;
|
||||||
public stream:DataStream;
|
public stream:DataStream;
|
||||||
private isLocked:boolean = false;
|
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.name = name;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.stream = stream;
|
this.stream = stream;
|
||||||
|
this._isSpecial = isSpecial;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get isSpecial() {
|
||||||
|
return this._isSpecial;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get userCount() {
|
public get userCount() {
|
||||||
|
|
|
@ -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");
|
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 {
|
export class Match {
|
||||||
/*public matchId:number = -1;
|
// osu! Data
|
||||||
|
public matchId:number = -1;
|
||||||
public inProgress:boolean = false;
|
public inProgress:boolean = false;
|
||||||
public matchType: 0;
|
public matchType:number = 0;
|
||||||
public activeMods: 0;
|
public activeMods:number = 0;
|
||||||
public gameName: "";
|
public gameName:string = "";
|
||||||
public gamePassword: '';
|
public gamePassword:string | undefined = '';
|
||||||
public beatmapName: '';
|
public beatmapName:string = '';
|
||||||
public beatmapId: 0;
|
public beatmapId:number = 0;
|
||||||
public beatmapChecksum: '';
|
public beatmapChecksum:string = '';
|
||||||
public slots: [];
|
public slots:Array<Slot> = new Array<Slot>();
|
||||||
public host:number = 0;
|
public host:number = 0;
|
||||||
public playMode:number = 0;
|
public playMode:number = 0;
|
||||||
public matchScoringType:number = 0;
|
public matchScoringType:number = 0;
|
||||||
|
@ -18,86 +45,91 @@ export class Match {
|
||||||
public specialModes:number = 0;
|
public specialModes:number = 0;
|
||||||
public seed:number = 0;
|
public seed:number = 0;
|
||||||
|
|
||||||
constructor(MatchData = {}) {
|
// Binato data
|
||||||
this.matchId = MatchData.matchId;
|
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.inProgress = matchData.inProgress;
|
||||||
this.matchStartCountdownActive = false;
|
|
||||||
|
|
||||||
this.matchType = MatchData.matchType;
|
this.matchType = matchData.matchType;
|
||||||
|
|
||||||
this.activeMods = MatchData.activeMods;
|
this.activeMods = matchData.activeMods;
|
||||||
|
|
||||||
this.gameName = MatchData.gameName;
|
this.gameName = matchData.gameName;
|
||||||
if (MatchData.gamePassword == '') MatchData.gamePassword == null;
|
if (matchData.gamePassword == '') matchData.gamePassword == null;
|
||||||
this.gamePassword = MatchData.gamePassword;
|
this.gamePassword = matchData.gamePassword;
|
||||||
|
|
||||||
this.beatmapName = MatchData.beatmapName;
|
this.beatmapName = matchData.beatmapName;
|
||||||
this.beatmapId = MatchData.beatmapId;
|
this.beatmapId = matchData.beatmapId;
|
||||||
this.beatmapChecksum = MatchData.beatmapChecksum;
|
this.beatmapChecksum = matchData.beatmapChecksum;
|
||||||
|
|
||||||
this.slots = MatchData.slots;
|
this.slots = matchData.slots;
|
||||||
for (let i = 0; i < this.slots.length; i++) {
|
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.matchScoringType = matchData.matchScoringType;
|
||||||
this.matchTeamType = MatchData.matchTeamType;
|
this.matchTeamType = matchData.matchTeamType;
|
||||||
this.specialModes = MatchData.specialModes;
|
this.specialModes = matchData.specialModes;
|
||||||
|
|
||||||
this.seed = MatchData.seed;
|
this.seed = matchData.seed;
|
||||||
|
|
||||||
this.matchStreamName = `mp_${this.matchId}`;
|
this.matchStream = sharedContent.streams.CreateStream(`multiplayer:match_${this.matchId}`);
|
||||||
this.matchChatStreamName = `mp_chat_${this.matchId}`;
|
this.matchChatChannel = sharedContent.chatManager.AddSpecialChatChannel("multiplayer", `mp_${this.matchId}`);
|
||||||
|
|
||||||
this.matchLoadSlots = null;
|
//this.matchLoadSlots = null;
|
||||||
this.matchSkippedSlots = null;
|
//this.matchSkippedSlots = null;
|
||||||
|
|
||||||
this.playerScores = null;
|
//this.playerScores = null;
|
||||||
|
|
||||||
this.multiplayerExtras = null;
|
//this.multiplayerExtras = null;
|
||||||
|
|
||||||
this.isTourneyMatch = false;
|
//this.isTourneyMatch = false;
|
||||||
this.tourneyClientUsers = [];
|
//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}) {
|
public static createMatch(matchHost:User, matchData:MatchData, sharedContent:SharedContent) : Promise<Match> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise<Match>(async (resolve, reject) => {
|
||||||
MatchData.matchId = (await global.DatabaseHelper.query(
|
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;",
|
"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"];
|
))[0]["id"];
|
||||||
|
|
||||||
const matchInstance = new MultiplayerMatch(MatchData);
|
const matchInstance = new Match(matchData, sharedContent);
|
||||||
|
|
||||||
console.log(matchInstance.matchId);
|
console.log(matchInstance.matchId);
|
||||||
|
|
||||||
// Update the status of the current user
|
// Update the status of the current user
|
||||||
StatusUpdate(MatchHost, MatchHost.id);
|
StatusUpdate(matchHost, matchHost.id);
|
||||||
|
|
||||||
const osuPacketWriter = new osu.Bancho.Writer;
|
const osuPacketWriter = new osu.Bancho.Writer;
|
||||||
|
|
||||||
osuPacketWriter.MatchNew(matchInstance.createOsuMatchJSON());
|
//osuPacketWriter.MatchNew(matchInstance.createOsuMatchJSON());
|
||||||
|
|
||||||
MatchHost.addActionToQueue(osuPacketWriter.toBuffer);
|
matchHost.addActionToQueue(osuPacketWriter.toBuffer);
|
||||||
|
|
||||||
Streams.addStream(matchInstance.matchStreamName, true, matchInstance.matchId);
|
|
||||||
Streams.addStream(matchInstance.matchChatStreamName, true, matchInstance.matchId);
|
|
||||||
|
|
||||||
// Update the match listing for users in the multiplayer lobby
|
// Update the match listing for users in the multiplayer lobby
|
||||||
global.MultiplayerManager.updateMatchListing();
|
//global.MultiplayerManager.updateMatchListing();
|
||||||
|
|
||||||
resolve(matchInstance);
|
resolve(matchInstance);
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getSlotIdByPlayerId(playerId = 0) {
|
/*getSlotIdByPlayerId(playerId = 0) {
|
||||||
const player = getUserById(playerId);
|
const player = getUserById(playerId);
|
||||||
|
|
||||||
if (player != null) return player.matchSlotId;
|
if (player != null) return player.matchSlotId;
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
export class Slot {
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@ import { RankingModes } from "../enums/RankingModes";
|
||||||
import { User } from "../objects/User";
|
import { User } from "../objects/User";
|
||||||
const osu = require("osu-packet");
|
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
|
if (id == 3) return; // Ignore Bot
|
||||||
|
|
||||||
// Create new osu packet writer
|
// Create new osu packet writer
|
||||||
|
|
Loading…
Reference in a new issue