initial merge of both repos

This commit is contained in:
2021-02-25 23:11:23 +01:00
commit e1ec6b2db9
138 changed files with 4282 additions and 0 deletions

View File

@@ -0,0 +1,532 @@
//imports
import * as log from '../util/logging.js'
import * as resp from '../interface/rest/response.js'
import { mkstring } from '../util/token.js'
import * as logic from './UnoRules.js'
import { UnoChat } from './UnoChat.js'
import { UnoSockets } from './UnoSocket.js'
import WebSocket from 'ws';
import jsonCards from '../../config/cards.json'
import jsonConf from '../../config/game.json'
import { shuffle } from '../util/shuffle.js'
import { UIVote } from './UiVote.js'
export interface UnoCard {
id: number;
color: string;
number: string;
tx: string;
}
export interface UnoPlayer {
nickname: string;
lastseen: Date;
userId: string;
ready: boolean;
uno: boolean;
cardDrawn: boolean;
score: number;
rounds: number;
hand: UnoCard[];
socket: WebSocket;
}1
export interface UnoExtraRules {
sw_stacking: boolean;
sw_jumpin: boolean;
sw_double: boolean;
sw_sleep: boolean;
sw_seveno: boolean;
}
export class UnoSession {
sessionID: number; //SitzungsID
players: UnoPlayer[]; //alle Spielerobjekte
winners: UnoPlayer[]; //fertige spieler
cardsPlayed: UnoCard[]; //gespielte Karten Satpel
cardsMixed: UnoCard[]; //nachziehkarten Stapel
started: boolean; //spiel gestartet
password: string; //passwort f<>r den zutritt
currentPlayer: string; //aktueller spieler
direction: number; //spielrichtung (1=vor, -1=zur<75>ck, 0=nicht gestartet)
startcards: number; //anzahl der maximalen karten
maxPlayers: number; //maximale spieleranzahl
serverName: string; //serever Name
unoChat: UnoChat;
sockets: UnoSockets;
lastPlayedBy: UnoPlayer;
testmode: boolean;
activeVote: UIVote;
sessionId: string;
canDelete: boolean;
extraRules: UnoExtraRules;
sleepTimer;
sleepValue;
stackSize: number; //anzahl der Karten die genzpgen werden müssen
private checkTimer;
constructor(sessionId,custom: any){
this.extraRules = {
sw_stacking: custom.sw_stacking ,
sw_jumpin: custom.sw_jumpin ,
sw_double: custom.sw_double ,
sw_sleep: custom.sw_sleep ,
sw_seveno: custom.sw_seveno ,
}
console.log(custom)
this.players= [];
this.winners= [];
this.unoChat= new UnoChat(this);
this.sockets= undefined;
this.sessionId= sessionId;
//konfigurationsdate laden
log.logNotice("Spiel Starten. Lade Konfigurationsdatei...");
let t_this = jsonConf;
this.password = t_this.password;
this.startcards = custom.startcards || t_this.startCards;
this.maxPlayers = t_this.maxPlayers;
this.serverName = t_this.serverName;
this.testmode = t_this.testMode;
this.sockets = new UnoSockets(this);
this.activeVote = undefined;
this.canDelete = false;
this.initLobby();
//kick inactive
this.checkTimer = setInterval(()=>{
[...this.players, ...this.winners].forEach(el =>{
var dif = ((new Date()).getTime()- el.lastseen.getTime())/1000;
if(!this.started && dif > 10){
this.kickUser(el, "10 Sekunden Inaktiv")
}else if(this.started && dif > 60){
this.kickUser(el, "60 Sekunden Inaktiv")
}else if(this.started && dif > 29 && dif < 31){
this.unoChat.writeMessage(el.nickname + " wird in 30 Sekunden wegen Inaktivität gekickt.")
}
else if(this.started && dif > 44 && dif < 46){
this.unoChat.writeMessage(el.nickname + " wird in 15 Sekunden wegen Inaktivität gekickt.")
}
})
if ([...this.players, ...this.winners].length == 0){
log.logInfo('Lobby empty. Closing...');
this.canDelete = true;
this.deleteSession();
}
},1000);
}
public deleteSession(){
[...this.players, ...this.winners].forEach(el => el.socket.close())
clearInterval(this.sockets.pingTimer)
clearInterval(this.checkTimer)
this.stopTimer();
}
private initLobby() {
this.cardsPlayed = []; //gespielte Karten Satpel
this.cardsMixed = []; //nachziehkarten Stapel
this.started = false; //spiel gestartet
this.currentPlayer = "";
this.direction = 0;
this.stackSize = 0;
//Karten Laden
log.logNotice("Spiel Starten. Lade Karten...");
let cards = jsonCards.cards;
let counter = 0;
cards.forEach(el => {
for (let i = 0; i < el.count; i++) {
this.cardsMixed.push({
id: counter,
color: el.color,
number: el.number,
tx: el.tx
});
counter++;
}
});
shuffle(this.cardsMixed); //Karten mischen
shuffle(this.cardsMixed); //Karten mischen
shuffle(this.cardsMixed); //Karten mischen
shuffle(this.cardsMixed); //Karten mischen
log.logNotice(this.cardsMixed.length.toString() + " Karten geladen.");
this.clientUpdateStatus();
}
public restartGame() {
this.players = [...this.players, ...this.winners]; //alle Spielerobjekte
this.winners = [];
shuffle(this.players);
this.players.forEach(player => {
player.hand = []; //übrige karten löschen
player.ready = false;
player.uno = false;
player.cardDrawn = false;
player.rounds++;
})
this.initLobby();
this.clientUpdateHands();
this.clientUpdateAllPlayers();
}
public playerJoin(nickname: string):any[] {
if (this.started) {
return [false,"Das Spiel wurde bereits gestartet."]
} else {
if (!nickname) {
log.logError("User tried to connect without Nickname")
return [false,"Du musst einen benutzernamen angeben."]
}
//wenn sonst soweit alles passt
const playerObj: UnoPlayer = {
nickname: nickname,
lastseen: new Date(),
userId: mkstring(20),
ready: false,
uno: false,
cardDrawn: false,
score: 0,
rounds: 1,
hand: [],
socket: undefined,
};
this.players.push(playerObj);
this.clientUpdatePlayer(playerObj);
log.logNotice("Player " + nickname + " joined with id " + playerObj.userId);
this.unoChat.writeMessage(nickname + " ist dem Spiel beigetreten");
return [true,{
userId: playerObj.userId
}]
}
}
public checkReady() {
let all = 0;
let ready = 0;
this.players.forEach(function (obj, ix) {
all++;
if (obj.ready) { ready++; }
});
log.logNotice(ready + "/" + all + " Players are ready");
this.unoChat.writeMessage(ready + "/" + all + " spieler sind Bereit");
if (all == ready && all > 1) {
log.logNotice("Start Game");
this.startGame();
logic.onStart(this);
}
}
public startGame() {
this.started = true;
log.logNotice("Starting Game. Dealing Cards");
for (let player_ix = 0; player_ix < this.players.length; player_ix++) {
let pObj = this.players[player_ix];
pObj.hand = [];
for (let i = 0; i < this.startcards; i++) {
pObj.hand.push(this.pullCardFromStack());
}
this.clientUpdatePlayer(pObj);
}
this.cardsPlayed.push(this.pullCardFromStack());
log.logNotice("Cards dealt");
this.unoChat.writeMessage("Die Runde wurde gestartet");
this.currentPlayer = this.players[0].userId;
this.direction = 1;
this.clientUpdatePlayedCard()
this.clientUpdateCurrentPlayer();
this.clientUpdateStatus();
this.clientUpdateHands();
}
private pullCardFromStack() {
let card = this.cardsMixed[this.cardsMixed.length - 1];
this.cardsMixed.pop();
log.logNotice("Pulled Card form Stack. Remaining: " + this.cardsMixed.length);
return card;
}
public register_socket(socket: WebSocket, id: string){
this.sockets.register_socket(socket,id);
}
public initClient(player: UnoPlayer) {
let respObj: any = {};
//add hands
let players_public = []
let players_winners = []
this.players.forEach((obj) => {
players_public.push(this.getPlayerMeta(obj));
});
this.winners.forEach((obj) => {
players_winners.push(this.getPlayerMeta(obj));
});
respObj.hand = player ? player.hand : [];
respObj.serverName = this.serverName;
respObj.cardsMixed = this.cardsMixed.length;
respObj.cardsPlayed = this.cardsPlayed;
respObj.started = this.started;
respObj.direction = this.direction;
respObj.currentPlayer = this.currentPlayer;
respObj.players = players_public;
respObj.winners = players_winners;
respObj.extraRules = this.extraRules;
respObj.extraRules.cards = this.startcards;
respObj.stack = this.stackSize;
player.socket.send(JSON.stringify({
initClientData: respObj
}))
}
public clientHearbeat(player: UnoPlayer){
player.lastseen = new Date();
}
public findPlayerIndex(id) {
let index = 0;
this.players.forEach((obj, ix) => {
if (obj.userId == id) {
index = ix;
}
});
return index;
}
public clientUpdatePlayer(player: UnoPlayer){ //modify or add player
[...this.players, ...this.winners].forEach(el =>{
if (el.socket && el.socket?.OPEN){
el.socket.send(JSON.stringify({
player: "modify",
data: this.getPlayerMeta(player)
}))
}
})
}
public clientRemovePlayer(player: UnoPlayer){ //remove player
[...this.players, ...this.winners].forEach(el =>{
if (el.socket && el.socket?.OPEN){
el.socket.send(JSON.stringify({
player: "remove",
data: this.getPlayerMeta(player)
}))
}
})
}
private getPlayerMeta(player: UnoPlayer){
return {
nickname: player.nickname,
lastseen: player.lastseen,
userId: player.userId,
ready: player.ready,
cards: player.hand ? player.hand.length : 0,
uno: player.uno,
score: player.score,
rounds: player.rounds,
}
}
public clientUpdateWinner(){ //modify or add player
let players_winners = []
this.winners.forEach((obj) => {
players_winners.push(this.getPlayerMeta(obj));
});
[...this.players, ...this.winners].forEach(el =>{
if (el.socket && el.socket?.OPEN){
el.socket.send(JSON.stringify({
player: "winners",
data: players_winners
}))
}
})
}
public clientUpdateAllPlayers(){
let players_public = []
let players_winners = []
this.players.forEach((obj) => {
players_public.push(this.getPlayerMeta(obj));
});
this.winners.forEach((obj) => {
players_winners.push(this.getPlayerMeta(obj));
});
[...this.players, ...this.winners].forEach(el =>{
if (el.socket && el.socket?.OPEN){
el.socket.send(JSON.stringify({
player: "all",
players: players_public,
winners: players_winners,
}))
}
})
}
public clientUpdatePlayedCard(){
[...this.players, ...this.winners].forEach(el =>{
if (el.socket && el.socket?.OPEN){
el.socket.send(JSON.stringify({
gameUpdate: "playedStack",
card: this.cardsPlayed,
}))
}
})
}
public clientUpdateCurrentPlayer(){
[...this.players, ...this.winners].forEach(el =>{
if (el.socket && el.socket?.OPEN){
el.socket.send(JSON.stringify({
gameUpdate: "currentPlayer",
currentplayer: this.currentPlayer,
direction: this.direction,
}))
}
})
}
public clientUpdateStatus(){
[...this.players, ...this.winners].forEach(el =>{
if (el.socket && el.socket?.OPEN){
el.socket.send(JSON.stringify({
gameUpdate: "status",
started: this.started
}))
}
})
}
public clientUpdateHands(){
this.players.forEach(el =>{
if (el.socket && el.socket?.OPEN){
el.socket.send(JSON.stringify({
hand: "all",
cards: el.hand
}))
}
})
}
public clientAddCard(player: UnoPlayer, card: UnoCard){ //modify or add player
if (player.socket && player.socket?.OPEN){
player.socket.send(JSON.stringify({
hand: "add",
card: card
}))
}
}
public clientRemoveCard(player: UnoPlayer, card: UnoCard){ //modify or add player
if (player.socket && player.socket?.OPEN){
player.socket.send(JSON.stringify({
hand: "remove",
card: card
}))
}
}
public kickUser(player: UnoPlayer, reason: string){
log.logNotice("Player " + player.nickname + " (" + player.userId + ") kicked for reason : " + reason);
this.unoChat.writeMessage(player.nickname + " wurde gekickt. Grund: " + reason);
if (player.socket && player.socket?.OPEN){
player.socket.send(JSON.stringify({kick:reason}));
}
if(this.started){
this.cardsMixed = [...player.hand, ...this.cardsMixed];
if (player.userId == this.currentPlayer) {
logic.advancePlayer(this, false, false);
}
}
this.winners = this.winners.filter(el2 => el2.userId != player.userId);
this.players = this.players.filter(el2 => el2.userId != player.userId);
this.clientUpdateAllPlayers();
}
public startTimer(duration: number, event: Function){
this.stopTimer();
this.sendTimer(duration);
this.sleepValue = duration;
this.sleepTimer = setInterval(()=>{
this.sleepValue --;
this.sendTimer(this.sleepValue);
if (this.sleepValue == -1){
this.stopTimer();
event();
}
},1000)
}
public stopTimer(){
if (this.sleepTimer){
clearInterval(this.sleepTimer)
}
}
private sendTimer(value: number){
[...this.players, ...this.winners].forEach(el =>{
if (el.socket && el.socket?.OPEN){
el.socket.send(JSON.stringify({
timer: value,
}))
}
})
}
public clientPlaySound(player: UnoPlayer, sound: string){
if (player.socket && player.socket?.OPEN){
player.socket.send(JSON.stringify({
sound: sound,
}))
}
}
public clientNotify(player: UnoPlayer, message: string, failed: boolean){
if (player.socket && player.socket?.OPEN){
player.socket.send(JSON.stringify({
notify: message,
warning: !failed,
}))
}
}
public addStackSize(value: number){
this.stackSize += value;
[...this.players, ...this.winners].forEach(el =>{
if (el.socket && el.socket?.OPEN){
el.socket.send(JSON.stringify({
stack: this.stackSize
}))
}
})
this.sendStackSize();
}
public resetStackSize(){
this.stackSize = 0;
this.sendStackSize();
}
private sendStackSize(){
[...this.players, ...this.winners].forEach(el =>{
if (el.socket && el.socket?.OPEN){
el.socket.send(JSON.stringify({
stack: this.stackSize
}))
}
})
}
}