This commit is contained in:
		
							parent
							
								
									649193069d
								
							
						
					
					
						commit
						27914e227f
					
				
					 5 changed files with 75 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -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",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,9 @@ export interface IGame {
 | 
			
		|||
	};
 | 
			
		||||
	form1: any;
 | 
			
		||||
	form2: any;
 | 
			
		||||
 | 
			
		||||
	// ログのposを文字列としてすべて連結したもののCRC32値
 | 
			
		||||
	crc32: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
			}));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue