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("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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -37,4 +37,12 @@ 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
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 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() {
|
||||
|
|
|
@ -1,103 +1,135 @@
|
|||
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;
|
||||
public matchTeamType:number = 0;
|
||||
public specialModes:number = 0;
|
||||
public seed: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(
|
||||
"INSERT INTO mp_matches (id, name, open_time, close_time, seed) VALUES (NULL, ?, UNIX_TIMESTAMP(), NULL, ?) RETURNING id;",
|
||||
[MatchData.gameName, MatchData.seed]
|
||||
))[0]["id"];
|
||||
|
||||
const matchInstance = new MultiplayerMatch(MatchData);
|
||||
|
||||
console.log(matchInstance.matchId);
|
||||
|
||||
// Update the status of the current user
|
||||
StatusUpdate(MatchHost, MatchHost.id);
|
||||
|
||||
const osuPacketWriter = new osu.Bancho.Writer;
|
||||
|
||||
osuPacketWriter.MatchNew(matchInstance.createOsuMatchJSON());
|
||||
|
||||
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
|
||||
global.MultiplayerManager.updateMatchListing();
|
||||
|
||||
resolve(matchInstance);
|
||||
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]
|
||||
))[0]["id"];
|
||||
|
||||
const matchInstance = new Match(matchData, sharedContent);
|
||||
|
||||
console.log(matchInstance.matchId);
|
||||
|
||||
// Update the status of the current user
|
||||
StatusUpdate(matchHost, matchHost.id);
|
||||
|
||||
const osuPacketWriter = new osu.Bancho.Writer;
|
||||
|
||||
//osuPacketWriter.MatchNew(matchInstance.createOsuMatchJSON());
|
||||
|
||||
matchHost.addActionToQueue(osuPacketWriter.toBuffer);
|
||||
|
||||
// Update the match listing for users in the multiplayer lobby
|
||||
//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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue