This commit is contained in:
syuilo 2018-03-11 17:23:59 +09:00
parent 649193069d
commit 27914e227f
5 changed files with 75 additions and 4 deletions

View file

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

View file

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

View file

@ -1,5 +1,6 @@
import * as websocket from 'websocket'; import * as websocket from 'websocket';
import * as redis from 'redis'; import * as redis from 'redis';
import * as CRC32 from 'crc-32';
import Game, { pack } from '../models/othello-game'; import Game, { pack } from '../models/othello-game';
import { publishOthelloGameStream } from '../event'; import { publishOthelloGameStream } from '../event';
import Othello from '../../common/othello/core'; import Othello from '../../common/othello/core';
@ -50,6 +51,11 @@ export default function(request: websocket.request, connection: websocket.connec
if (msg.pos == null) return; if (msg.pos == null) return;
set(msg.pos); set(msg.pos);
break; 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 //#endregion
publishOthelloGameStream(gameId, 'started', await pack(gameId)); publishOthelloGameStream(gameId, 'started', await pack(gameId, user));
}, 3000); }, 3000);
} }
} }
// 石を打つ
async function set(pos) { async function set(pos) {
const game = await Game.findOne({ _id: gameId }); const game = await Game.findOne({ _id: gameId });
@ -278,10 +285,13 @@ export default function(request: websocket.request, connection: websocket.connec
pos pos
}; };
const crc32 = CRC32.str(game.logs.map(x => x.pos.toString()).join('') + pos.toString());
await Game.update({ await Game.update({
_id: gameId _id: gameId
}, { }, {
$set: { $set: {
crc32,
is_ended: o.isEnded, is_ended: o.isEnded,
winner_id: winner 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"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import * as CRC32 from 'crc-32';
import Othello, { Color } from '../../../../../common/othello/core'; import Othello, { Color } from '../../../../../common/othello/core';
import { url } from '../../../config'; import { url } from '../../../config';
export default Vue.extend({ export default Vue.extend({
props: ['game', 'connection'], props: ['initGame', 'connection'],
data() { data() {
return { return {
game: null,
o: null as Othello, o: null as Othello,
logs: [], logs: [],
logPos: 0 logPos: 0,
pollingClock: null
}; };
}, },
@ -104,6 +107,8 @@ export default Vue.extend({
}, },
created() { created() {
this.game = this.initGame;
this.o = new Othello(this.game.settings.map, { this.o = new Othello(this.game.settings.map, {
isLlotheo: this.game.settings.is_llotheo, isLlotheo: this.game.settings.is_llotheo,
canPutEverywhere: this.game.settings.can_put_everywhere, canPutEverywhere: this.game.settings.can_put_everywhere,
@ -116,14 +121,29 @@ export default Vue.extend({
this.logs = this.game.logs; this.logs = this.game.logs;
this.logPos = this.logs.length; 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() { mounted() {
this.connection.on('set', this.onSet); this.connection.on('set', this.onSet);
this.connection.on('rescue', this.onRescue);
}, },
beforeDestroy() { beforeDestroy() {
this.connection.off('set', this.onSet); this.connection.off('set', this.onSet);
this.connection.off('rescue', this.onRescue);
clearInterval(this.pollingClock);
}, },
methods: { methods: {
@ -181,6 +201,27 @@ export default Vue.extend({
this.game.winner = null; 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> <template>
<div> <div>
<x-room v-if="!g.is_started" :game="g" :connection="connection"/> <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> </div>
</template> </template>