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",
 | 
							"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",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,6 +35,9 @@ export interface IGame {
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	form1: any;
 | 
						form1: any;
 | 
				
			||||||
	form2: any;
 | 
						form2: any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ログのposを文字列としてすべて連結したもののCRC32値
 | 
				
			||||||
 | 
						crc32: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
 | 
								}));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue