This commit is contained in:
syuilo 2018-03-11 17:23:59 +09:00
parent bd3714e7c9
commit 6d383893dc
5 changed files with 75 additions and 4 deletions

View file

@ -92,6 +92,7 @@
"compression": "1.7.2",
"cookie": "0.3.1",
"cors": "2.8.4",
"crc-32": "^1.2.0",
"css-loader": "0.28.10",
"debug": "3.1.0",
"deep-equal": "1.0.1",

View file

@ -35,6 +35,9 @@ export interface IGame {
};
form1: any;
form2: any;
// ログのposを文字列としてすべて連結したもののCRC32値
crc32: string;
}
/**

View file

@ -1,5 +1,6 @@
import * as websocket from 'websocket';
import * as redis from 'redis';
import * as CRC32 from 'crc-32';
import Game, { pack } from '../models/othello-game';
import { publishOthelloGameStream } from '../event';
import Othello from '../../common/othello/core';
@ -50,6 +51,11 @@ export default function(request: websocket.request, connection: websocket.connec
if (msg.pos == null) return;
set(msg.pos);
break;
case 'check':
if (msg.crc32 == null) return;
check(msg.crc32);
break;
}
});
@ -231,11 +237,12 @@ export default function(request: websocket.request, connection: websocket.connec
}
//#endregion
publishOthelloGameStream(gameId, 'started', await pack(gameId));
publishOthelloGameStream(gameId, 'started', await pack(gameId, user));
}, 3000);
}
}
// 石を打つ
async function set(pos) {
const game = await Game.findOne({ _id: gameId });
@ -278,10 +285,13 @@ export default function(request: websocket.request, connection: websocket.connec
pos
};
const crc32 = CRC32.str(game.logs.map(x => x.pos.toString()).join('') + pos.toString());
await Game.update({
_id: gameId
}, {
$set: {
crc32,
is_ended: o.isEnded,
winner_id: winner
},
@ -300,4 +310,20 @@ export default function(request: websocket.request, connection: websocket.connec
});
}
}
async function check(crc32) {
const game = await Game.findOne({ _id: gameId });
if (!game.is_started) return;
// 互換性のため
if (game.crc32 == null) return;
if (crc32 !== game.crc32) {
connection.send(JSON.stringify({
type: 'rescue',
body: await pack(game, user)
}));
}
}
}

View file

@ -37,17 +37,20 @@
<script lang="ts">
import Vue from 'vue';
import * as CRC32 from 'crc-32';
import Othello, { Color } from '../../../../../common/othello/core';
import { url } from '../../../config';
export default Vue.extend({
props: ['game', 'connection'],
props: ['initGame', 'connection'],
data() {
return {
game: null,
o: null as Othello,
logs: [],
logPos: 0
logPos: 0,
pollingClock: null
};
},
@ -104,6 +107,8 @@ export default Vue.extend({
},
created() {
this.game = this.initGame;
this.o = new Othello(this.game.settings.map, {
isLlotheo: this.game.settings.is_llotheo,
canPutEverywhere: this.game.settings.can_put_everywhere,
@ -116,14 +121,29 @@ export default Vue.extend({
this.logs = this.game.logs;
this.logPos = this.logs.length;
//
if (this.game.is_started && !this.game.is_ended) {
this.pollingClock = setInterval(() => {
const crc32 = CRC32.str(this.logs.map(x => x.pos.toString()).join(''));
this.connection.send({
type: 'check',
crc32
});
}, 10000);
}
},
mounted() {
this.connection.on('set', this.onSet);
this.connection.on('rescue', this.onRescue);
},
beforeDestroy() {
this.connection.off('set', this.onSet);
this.connection.off('rescue', this.onRescue);
clearInterval(this.pollingClock);
},
methods: {
@ -181,6 +201,27 @@ export default Vue.extend({
this.game.winner = null;
}
}
},
//
onRescue(game) {
this.game = game;
this.o = new Othello(this.game.settings.map, {
isLlotheo: this.game.settings.is_llotheo,
canPutEverywhere: this.game.settings.can_put_everywhere,
loopedBoard: this.game.settings.looped_board
});
this.game.logs.forEach(log => {
this.o.put(log.color, log.pos);
});
this.logs = this.game.logs;
this.logPos = this.logs.length;
this.checkEnd();
this.$forceUpdate();
}
}
});

View file

@ -1,7 +1,7 @@
<template>
<div>
<x-room v-if="!g.is_started" :game="g" :connection="connection"/>
<x-game v-else :game="g" :connection="connection"/>
<x-game v-else :init-game="g" :connection="connection"/>
</div>
</template>