Skip to content

Commit 8efe3ea

Browse files
committed
use built-in identity in blind room
1 parent d74ae6c commit 8efe3ea

File tree

13 files changed

+300
-34
lines changed

13 files changed

+300
-34
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,7 @@ config/
22
node_modules/
33
/client/static/assets/main
44
/client/static/front-assets
5-
/server/themes
5+
/server/themes/*
6+
!/server/themes/example.coffee
7+
!/server/themes/readme.md
68
/language/*/*.missing.json

client/code/pages/game/game.coffee

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,15 @@ exports.start=(roomid)->
124124
modal: true
125125
message: String result.error
126126
}
127+
else if result?.tip?
128+
# To show player who he is.
129+
dialog.showMessageDialog {
130+
modal: false
131+
title: result.title
132+
message: String result.tip
133+
ok: i18n.t 'common:messageDialog.close'
134+
}
135+
Index.app.refresh()
127136
else
128137
# succeeded to login
129138
Index.app.refresh()
@@ -304,6 +313,7 @@ exports.start=(roomid)->
304313
joined: Boolean enter_result?.joined
305314
old: room.old
306315
blind: !!room.blind
316+
theme: room.theme? && !!room.theme
307317
}
308318
else if obj.game?.finished
309319
{
@@ -317,6 +327,7 @@ exports.start=(roomid)->
317327
joined: false
318328
old: false
319329
blind: !!room.blind
330+
theme: room.theme? && !!room.theme
320331
}
321332
else
322333
null

client/code/pages/game/newroom.coffee

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,21 @@ exports.start=->
3030
if ch.name=="usepassword"
3131
$("#newroomform").get(0).elements["password"].disabled = !ch.checked
3232

33+
ss.rpc "game.themes.getThemeList",(docs)->
34+
if docs.error?
35+
# ?
36+
console.error docs.error
37+
return
38+
$("#theme").empty()
39+
select=$("#theme").get 0
40+
opt=document.createElement "option"
41+
opt.value = ""
42+
opt.textContent = "なし"
43+
select.appendChild opt
44+
45+
docs.forEach (doc)->
46+
opt=document.createElement "option"
47+
opt.value = doc.value
48+
opt.textContent = doc.name
49+
select.appendChild opt
50+

client/templates/game/newroom.jade

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ section.rooms
2727
option(value="",selected) なし
2828
option(value="yes") あり(終了後に公開)
2929
option(value="complete") あり(最後まで非公開)
30+
p
31+
label(title="覆面がありに設定された後、全プレイヤーの名前がサーバーによってランダムに選択されます。")
32+
| テーマ
33+
select(id="theme",name="theme")
3034
p
3135
label(title="ありにすると、ルームを建てた人はGMになります")
3236
| GM

front/src/pages/game-view/defs/room.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ export interface RoomPrelude {
1919
* Whether this room is blind mode.
2020
*/
2121
blind: boolean;
22+
/**
23+
* Whether this room has a theme.
24+
*/
25+
theme: boolean;
2226
}
2327
/**
2428
* State of room after the end.

front/src/pages/game-view/room-controls/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,10 @@ export class RoomControls extends React.Component<IPropRoomControls, {}> {
106106
private handleJoinClick(): void {
107107
const { t, roomControls, handlers } = this.props;
108108
const blind = roomControls.type === 'prelude' && roomControls.blind;
109+
const theme = roomControls.type === 'prelude' && roomControls.theme;
109110
// if the room is in blind mode,
110111
// show user info dialog.
111-
if (blind) {
112+
if (blind && !theme) {
112113
showPlayerDialog({
113114
modal: true,
114115
title: t('game_client:room.playerDialog.title'),

language/ja/game.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ judge:
231231
lonewolf: "人狼は最後の村人を喰い殺すと次の獲物を求めて独り去っていくのだった……"
232232
raven: "村は鴉に支配されました。"
233233
draw: "引き分けになりました。"
234+
scapegoat: "村は身代わりくんに支配されました。"
234235
# short summary
235236
short:
236237
human: "村人勝利"

language/ja/rooms.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ error:
2323
# Cannot make a room because banned
2424
banned: "アクセス制限により、部屋を作成できません。"
2525

26+
theme:
27+
# nonexistent theme
28+
noTheme: "このテーマは存在しません。"
29+
# This theme is unavailable right now.
30+
notAvailable: "テーマの「{{name}}」は現在利用できません。"
31+
# This theme cannot be locked.
32+
notLockable: "テーマの「{{name}}」はパスワードを使用できません。"
33+
# A room with theme must be blind.
34+
notBlind: "テーマを使用している部屋は覆面でなければなりません。"
35+
# The number of players cannot be greater than the number of built-in skins of the theme.
36+
playerTooMuch: "テーマの「{{name}}」の最大人数は「{{length}}」です。"
37+
2638
join:
2739
# Cannot join because banned
2840
banned: "アクセス制限により、部屋に参加できません。"

server/rpc/game/game.coffee

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,13 @@ module.exports=
204204
else
205205
# 接続
206206
pr+=x.value
207-
if pr
208-
name="#{Server.prize.prizeQuote pr}#{name}"
207+
# theme may have built-in prize.
208+
if room.blind in ["complete","yes"] && room.theme
209+
theme = Server.game.themes.getTheme room.theme
210+
if theme != null && player.tpr
211+
pr = player.tpr
212+
if pr
213+
name="#{Server.prize.prizeQuote pr}#{name}"
209214

210215
game = games[room.id]
211216
unless game && !game.participants.some((p)->p.realid==player.realid)
@@ -364,6 +369,7 @@ Server=
364369
game:
365370
game:module.exports
366371
rooms:require './rooms.coffee'
372+
themes:require './themes.coffee'
367373
prize:require '../../prize.coffee'
368374
oauth:require '../../oauth.coffee'
369375
log:require '../../log.coffee'
@@ -2205,6 +2211,10 @@ class Game
22052211
[@i18n.t("judge.lonewolf"),@i18n.t("judge.short.lonewolf")]
22062212
when "Draw"
22072213
[@i18n.t("judge.draw"),""]
2214+
# 身代わりくん单独勝利
2215+
winpl = @players.filter (x)->x.winner
2216+
if(winpl.length==1 && winpl[0].realid=="身代わりくん")
2217+
resultstring = @i18n.t("judge.scapegoat")
22082218
if teamstring
22092219
log.comment = @i18n.t "system.judge", {short: teamstring, result: resultstring}
22102220
else
@@ -4527,9 +4537,9 @@ class Spellcaster extends Player
45274537
return game.i18n.t "error.common.alreadyUsed"
45284538
arr=[]
45294539
try
4530-
arr=JSON.parse @flag
4540+
arr=JSON.parse @flag
45314541
catch error
4532-
arr=[]
4542+
arr=[]
45334543
unless arr instanceof Array
45344544
arr=[]
45354545
if playerid in arr
@@ -6459,18 +6469,18 @@ class PsychoKiller extends Madman
64596469
touched:(game,from)->
64606470
# 殺すリストに追加する
64616471
fl=try
6462-
JSON.parse @flag || "[]"
6463-
catch e
6464-
[]
6472+
JSON.parse @flag || "[]"
6473+
catch e
6474+
[]
64656475
fl.push from
64666476
@setFlag JSON.stringify fl
64676477
sunset:(game)->
64686478
@setFlag "[]"
64696479
midnight:(game,midnightSort)->
64706480
fl=try
6471-
JSON.parse @flag || "[]"
6472-
catch e
6473-
[]
6481+
JSON.parse @flag || "[]"
6482+
catch e
6483+
[]
64746484
for id in fl
64756485
pl=game.getPlayer id
64766486
if pl? && !pl.dead
@@ -8377,9 +8387,9 @@ class Waiting extends Player
83778387
formType: FormType.required
83788388
sleeping:(game)->game.phase != Phase.rolerequesting || game.rolerequesttable[@id]?
83798389
isListener:(game,log)->
8380-
if log.mode=="audience"
8381-
true
8382-
else super
8390+
if log.mode=="audience"
8391+
true
8392+
else super
83838393
getSpeakChoice:(game)->
83848394
return ["prepare"]
83858395
getOpenForms:(game)->
@@ -8429,10 +8439,10 @@ class Watching extends Player
84298439
sleeping:(game)->true
84308440
isWinner:(game,team)->true
84318441
isListener:(game,log)->
8432-
if log.mode in ["audience","inlog"]
8433-
# 参加前なので
8434-
true
8435-
else super
8442+
if log.mode in ["audience","inlog"]
8443+
# 参加前なので
8444+
true
8445+
else super
84368446
getSpeakChoice:(game)->
84378447
return ["audience"]
84388448
getSpeakChoiceDay:(game)->
@@ -10867,6 +10877,14 @@ module.exports.actions=(req,res,ss)->
1086710877
ss.publish.channel "room#{roomid}","refresh",{id:roomid}
1086810878
else
1086910879
res result
10880+
# theme may have custom opening
10881+
if room.blind in ["complete","yes"] && room.theme
10882+
theme = Server.game.themes.getTheme room.theme
10883+
if theme != null && theme.opening
10884+
log=
10885+
mode:"system"
10886+
comment:theme.opening
10887+
splashlog game.id,game,log
1087010888
# 情報を開示
1087110889
getlog:(roomid)->
1087210890
M.games.findOne {id:roomid}, (err,doc)=>

server/rpc/game/rooms.coffee

Lines changed: 86 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ room: {
1717
mode: "waiting"/"playing"/"end"
1818
made: Time(Number)(作成された日時)
1919
blind:""/"yes"/"complete"
20+
theme: String(theme of room)
2021
number: Number(プレイヤー数)
2122
players:[PlayerObject,PlayerObject,...]
2223
gm: Booelan(trueならオーナーGM)
@@ -46,8 +47,10 @@ Server=
4647
game:
4748
game:require './game.coffee'
4849
rooms:module.exports
50+
themes:require './themes.coffee'
4951
oauth:require '../../oauth.coffee'
5052
log:require '../../log.coffee'
53+
crypto=require 'crypto'
5154
# ヘルパーセット処理
5255
sethelper=(ss,roomid,userid,id,res)->
5356
Server.game.rooms.oneRoomS roomid,(room)->
@@ -221,6 +224,29 @@ module.exports.actions=(req,res,ss)->
221224
jobrule:null
222225
room.password=query.password ? null
223226
room.blind=query.blind
227+
room.theme=query.theme
228+
if room.theme
229+
theme = Server.game.themes.getTheme room.theme
230+
unless theme
231+
res {error: i18n.t "error.theme.noTheme"}
232+
return
233+
if !theme.isAvailable?()
234+
res {error: i18n.t "error.theme.notAvailable", {name: theme.name}}
235+
return
236+
if !theme.lockable && room.password
237+
res {error: i18n.t "error.theme.notLockable", {name: theme.name}}
238+
return
239+
if room.blind == ""
240+
res {error: i18n.t "error.theme.notBlind"}
241+
return
242+
243+
skins = Object.keys theme.skins
244+
if room.number > skins.length
245+
res {error: i18n.t "error.theme.playerTooMuch", {
246+
name: theme.name
247+
length: skins.length
248+
}}
249+
return
224250
room.comment=query.comment ? ""
225251
#unless room.blind
226252
# room.players.push req.session.user
@@ -334,38 +360,83 @@ module.exports.actions=(req,res,ss)->
334360
if user.icon?.length > Config.maxlength.user.icon
335361
res error: i18n.t "error.join.iconTooLong"
336362
return
363+
364+
if room.theme
365+
theme = Server.game.themes.getTheme room.theme
366+
if theme == null
367+
res {error: i18n.t "error.theme.noTheme"}
368+
return
369+
if !theme.isAvailable?()
370+
res {error: i18n.t "error.theme.notAvailable", {name: theme.name}}
371+
return
372+
337373
if room.blind
338-
unless opt?.name
374+
unless opt?.name || room.theme
339375
res error: i18n.t "error.join.nameNeeded"
340376
return
341377
if opt.name.length > Config.maxlength.user.name
342378
res {error: i18n.t "error.join.nameTooLong"}
343379
return
380+
# テーマmode
381+
if room.theme && theme != null
382+
skins = Object.keys theme.skins
383+
skins = skins.filter((x)->!room.players.some((pl)->theme.skins[x].name==pl.name))
384+
skin = skins[Math.floor(Math.random() * skins.length)]
385+
386+
user.name=theme.skins[skin].name.trim()
387+
loop
388+
user.userid=crypto.randomBytes(10).toString('hex')
389+
if user.userid? && room.players.every((pl)->user.userid!=pl.userid)
390+
break
391+
392+
avatar = theme.skins[skin].avatar
393+
# his icon could be Array or a link.
394+
if Array.isArray avatar
395+
avatar = avatar[Math.floor(Math.random() * avatar.length)]
396+
user.icon= avatar ? null
344397
# 覆面
345-
makeid=-> # ID生成
346-
re=""
347-
while !re
348-
i=0
349-
while i<20
350-
re+="0123456789abcdef"[Math.floor Math.random()*16]
351-
i++
352-
if room.players.some((x)->x.userid==re)
353-
re=""
354-
re
355-
user.name=opt.name
356-
user.userid=makeid()
357-
user.icon= opt.icon ? null
398+
else
399+
makeid=-> # ID生成
400+
re=""
401+
while !re
402+
i=0
403+
while i<20
404+
re+="0123456789abcdef"[Math.floor Math.random()*16]
405+
i++
406+
if room.players.some((x)->x.userid==re)
407+
re=""
408+
re
409+
user.name=opt.name
410+
user.userid=makeid()
411+
user.icon= opt.icon ? null
358412
if user.name.trim() == ''
359413
res error: i18n.t "error.join.nameOnlySpaces"
360414
return
361415
M.rooms.update {id:roomid},{$push: {players:user}},(err)=>
362416
if err?
363417
res error: String err
364418
else
365-
res null
419+
if room.theme && theme != null
420+
# show player who he is.
421+
pr = theme.skins[skin].prize
422+
# his prize could be Array
423+
if Array.isArray pr
424+
pr = pr[Math.floor(Math.random() * pr.length)]
425+
# pass it to Server.game.game.inlog
426+
if pr
427+
user.tpr = pr
428+
name = "#{user.tpr}#{user.name}"
429+
else
430+
name = "#{user.name}"
431+
res
432+
tip: "#{name}"
433+
title:"#{theme.skin_tip}"
434+
else
435+
res null
366436
# 入室通知
367437
delete user.ip
368438
Server.game.game.inlog room,user
439+
delete user.tpr
369440
if room.blind
370441
delete user.realid
371442
if room.mode!="playing"

0 commit comments

Comments
 (0)