diff --git a/packages/backend/src/core/GlobalEventService.ts b/packages/backend/src/core/GlobalEventService.ts
index 29a97e94cd..560c5e45d1 100644
--- a/packages/backend/src/core/GlobalEventService.ts
+++ b/packages/backend/src/core/GlobalEventService.ts
@@ -172,18 +172,14 @@ export interface ReversiEventTypes {
 export interface ReversiGameEventTypes {
 	accept: boolean;
 	cancelAccept: undefined;
+	changeAcceptingStates: {
+		user1: boolean;
+		user2: boolean;
+	};
 	updateSettings: {
 		key: string;
 		value: any;
 	};
-	initForm: {
-		userId: MiUser['id'];
-		form: any;
-	};
-	updateForm: {
-		id: string;
-		value: any;
-	};
 	message: {
 		message: string;
 	};
@@ -193,6 +189,13 @@ export interface ReversiGameEventTypes {
 	check: {
 		crc32: string;
 	};
+	started: {
+		game: Packed<'ReversiGame'>;
+	};
+	ended: {
+		winnerId: MiUser['id'] | null;
+		game: Packed<'ReversiGame'>;
+	};
 }
 //#endregion
 
diff --git a/packages/backend/src/core/ReversiService.ts b/packages/backend/src/core/ReversiService.ts
index c2b611ce5e..126b211066 100644
--- a/packages/backend/src/core/ReversiService.ts
+++ b/packages/backend/src/core/ReversiService.ts
@@ -137,7 +137,7 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
 				user1Accepted: isAccepted,
 			});
 
-			this.globalEventService.publishReversiGameStream(game.id, 'changeAccepts', {
+			this.globalEventService.publishReversiGameStream(game.id, 'changeAcceptingStates', {
 				user1: isAccepted,
 				user2: game.user2Accepted,
 			});
@@ -148,7 +148,7 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
 				user2Accepted: isAccepted,
 			});
 
-			this.globalEventService.publishReversiGameStream(game.id, 'changeAccepts', {
+			this.globalEventService.publishReversiGameStream(game.id, 'changeAcceptingStates', {
 				user1: game.user1Accepted,
 				user2: isAccepted,
 			});
@@ -216,12 +216,32 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
 				}
 				//#endregion
 
-				this.globalEventService.publishReversiGameStream(game.id, 'started',
-					await this.reversiGameEntityService.pack(game.id, user));
+				this.globalEventService.publishReversiGameStream(game.id, 'started', {
+					game: await this.reversiGameEntityService.pack(game.id, user),
+				});
 			}, 3000);
 		}
 	}
 
+	@bindThis
+	public async updateSettings(game: MiReversiGame, user: MiUser, key: string, value: any) {
+		if (game.isStarted) return;
+		if ((game.user1Id !== user.id) && (game.user2Id !== user.id)) return;
+		if ((game.user1Id === user.id) && game.user1Accepted) return;
+		if ((game.user2Id === user.id) && game.user2Accepted) return;
+
+		if (!['map', 'bw', 'isLlotheo', 'canPutEverywhere', 'loopedBoard'].includes(key)) return;
+
+		await this.reversiGamesRepository.update(game.id, {
+			[key]: value,
+		});
+
+		this.globalEventService.publishReversiGameStream(game.id, 'updateSettings', {
+			key: key,
+			value: value,
+		});
+	}
+
 	@bindThis
 	public async putStoneToGame(game: MiReversiGame, user: MiUser, pos: number) {
 		if (!game.isStarted) return;
diff --git a/packages/backend/src/server/api/stream/channels/reversi-game.ts b/packages/backend/src/server/api/stream/channels/reversi-game.ts
index 52cf882e0b..be679c401b 100644
--- a/packages/backend/src/server/api/stream/channels/reversi-game.ts
+++ b/packages/backend/src/server/api/stream/channels/reversi-game.ts
@@ -46,8 +46,6 @@ class ReversiGameChannel extends Channel {
 			case 'accept': this.accept(true); break;
 			case 'cancelAccept': this.accept(false); break;
 			case 'updateSettings': this.updateSettings(body.key, body.value); break;
-			case 'initForm': this.initForm(body); break;
-			case 'updateForm': this.updateForm(body.id, body.value); break;
 			case 'message': this.message(body); break;
 			case 'putStone': this.putStone(body.pos); break;
 			case 'check': this.check(body.crc32); break;
@@ -58,81 +56,11 @@ class ReversiGameChannel extends Channel {
 	private async updateSettings(key: string, value: any) {
 		if (this.user == null) return;
 
+		// TODO: キャッシュしたい
 		const game = await this.reversiGamesRepository.findOneBy({ id: this.gameId! });
 		if (game == null) throw new Error('game not found');
 
-		if (game.isStarted) return;
-		if ((game.user1Id !== this.user.id) && (game.user2Id !== this.user.id)) return;
-		if ((game.user1Id === this.user.id) && game.user1Accepted) return;
-		if ((game.user2Id === this.user.id) && game.user2Accepted) return;
-
-		if (!['map', 'bw', 'isLlotheo', 'canPutEverywhere', 'loopedBoard'].includes(key)) return;
-
-		await this.reversiGamesRepository.update(this.gameId!, {
-			[key]: value,
-		});
-
-		publishReversiGameStream(this.gameId!, 'updateSettings', {
-			key: key,
-			value: value,
-		});
-	}
-
-	@bindThis
-	private async initForm(form: any) {
-		if (this.user == null) return;
-
-		const game = await this.reversiGamesRepository.findOneBy({ id: this.gameId! });
-		if (game == null) throw new Error('game not found');
-
-		if (game.isStarted) return;
-		if ((game.user1Id !== this.user.id) && (game.user2Id !== this.user.id)) return;
-
-		const set = game.user1Id === this.user.id ? {
-			form1: form,
-		} : {
-			form2: form,
-		};
-
-		await this.reversiGamesRepository.update(this.gameId!, set);
-
-		publishReversiGameStream(this.gameId!, 'initForm', {
-			userId: this.user.id,
-			form,
-		});
-	}
-
-	@bindThis
-	private async updateForm(id: string, value: any) {
-		if (this.user == null) return;
-
-		const game = await this.reversiGamesRepository.findOneBy({ id: this.gameId! });
-		if (game == null) throw new Error('game not found');
-
-		if (game.isStarted) return;
-		if ((game.user1Id !== this.user.id) && (game.user2Id !== this.user.id)) return;
-
-		const form = game.user1Id === this.user.id ? game.form2 : game.form1;
-
-		const item = form.find((i: any) => i.id == id);
-
-		if (item == null) return;
-
-		item.value = value;
-
-		const set = game.user1Id === this.user.id ? {
-			form2: form,
-		} : {
-			form1: form,
-		};
-
-		await this.reversiGamesRepository.update(this.gameId!, set);
-
-		publishReversiGameStream(this.gameId!, 'updateForm', {
-			userId: this.user.id,
-			id,
-			value,
-		});
+		this.reversiService.updateSettings(game, this.user, key, value);
 	}
 
 	@bindThis