19,509 バイト追加
、 2019年6月24日 (月) 01:49
[[どどんとふ]]からの[[BCDice]]の呼び出し方。このページでは、Rubyで書かれたどどんとふのサーバのダイス関連の処理を扱う。[https://github.com/torgtaitai/DodontoF/tree/d3e4cc374885986efc761cfabbb19e4b35e815e0 v1.49.04.01]のソースコードを参考にしている。
== ファイルの役割 ==
どどんとふのサーバでは、ダイスボットとの通信の処理は以下のファイルに記述されている。
* [https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/dodontof/dice_adapter.rb src_ruby/dodontof/dice_adapter.rb]:BCDiceとのアダプタ
* [https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/diceBotInfos.rb src_ruby/diceBotInfos.rb]:ダイスボットの情報を取得する処理
* [https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb DodontoFServer.rb]:サーバ本体
== src_ruby/dodontof/dice_adapter.rb:BCDiceとのアダプタ ==
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/dodontof/dice_adapter.rb
=== L7-L10:<code>DiceAdapter#initialize</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/dodontof/dice_adapter.rb#L7-L10
アダプタを初期化する。
* <code>@dir</code>:部屋固有のデータ保存ディレクトリが設定される。詳細は「[[#L164-L185:@dice_adapter の初期化]]」で解説する。
* <code>@diceBotTablePrefix</code>:必ず <code>'diceBotTable_'</code> が設定される。
<syntaxhighlight lang="ruby">
def initialize(dir, prefix)
@logger = DodontoF::Logger.instance
@dir = dir
@diceBotTablePrefix = prefix
end
</syntaxhighlight>
=== L13-L34:<code>DiceAdapter#rollDice</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/dodontof/dice_adapter.rb#L13-L34
ダイスロールを行う。メッセージ、ゲームシステム、出目を返すかが指定できる。結果のメッセージ、シークレットダイスかどうか、出目が返る。結果のメッセージの <code>'>'</code> は <code>'→'</code> に置換され、末尾の改行コードは削除される。
<syntaxhighlight lang="ruby">
def rollDice(params)
require 'cgiDiceBot.rb'
message = params['message']
gameType = params['gameType']
isNeedResult = params['isNeedResult']
@logger.debug(message, 'rollDice message')
@logger.debug(gameType, 'rollDice gameType')
bot = CgiDiceBot.new
result, randResults = bot.roll(message, gameType, @dir, @diceBotTablePrefix, isNeedResult)
result.gsub!(/>/, '→')
result.sub!(/\r?\n?\Z/m, '')
@logger.debug(result, 'rollDice result')
@logger.debug(randResults, 'rollDice randResults')
return result, bot.isSecret, randResults
end
</syntaxhighlight>
=== L36-L45:<code>DiceAdapter#getGameCommandInfos</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/dodontof/dice_adapter.rb#L36-L45
<syntaxhighlight lang="ruby">
def getGameCommandInfos
require 'cgiDiceBot.rb'
bot = CgiDiceBot.new
@logger.debug(@dir, 'dir')
commandInfos = bot.getGameCommandInfos(@dir, @diceBotTablePrefix)
@logger.debug(commandInfos, "getGameCommandInfos End commandInfos")
return commandInfos
end
</syntaxhighlight>
== src_ruby/diceBotInfos.rb:ダイスボットの情報を取得する処理 ==
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/diceBotInfos.rb
=== L69-L102:<code>DiceBotInfos.get</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/diceBotInfos.rb#L69-L102
<syntaxhighlight lang="ruby">
# ダイスボットの情報の一覧を取得する
# @param [Array<String>] orderedGameNames 順序付けられたゲーム名の配列
# @param [Boolean] showAllDiceBots すべてのダイスボットを表示するか
# @return [Array<Hash>]
def self.get(orderedGameNames, showAllDiceBots)
diceBots = DiceBotLoader.collectDiceBots
# ゲーム名 => ダイスボットの対応を作る
diceBotFor = Hash[
diceBots.map { |diceBot| [diceBot.gameName, diceBot] }
]
toDiceBot = lambda { |gameName| diceBotFor[gameName] }
orderedEnabledDiceBots = orderedGameNames.
map(&toDiceBot).
# ゲーム名が誤記されていた場合nilになるので除く
compact
orderedDiceBots =
if showAllDiceBots
disabledGameNames = diceBotFor.keys - orderedGameNames
orderedDisabledDiceBots = disabledGameNames.
sort.
map(&toDiceBot)
# 一覧に記載されていたゲーム→記載されていなかったゲームの順
orderedEnabledDiceBots + orderedDisabledDiceBots
else
orderedEnabledDiceBots
end
# 指定なし→各ゲーム→基本の順で返す
[NONE_DICE_BOT_INFO] + orderedDiceBots.map(&:info) + [BASE_DICE_BOT_INFO]
end
</syntaxhighlight>
=== L104-150:<code>DiceBotInfos.withTableCommands</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/src_ruby/diceBotInfos.rb#L104-150
<syntaxhighlight lang="ruby">
# テーブルのコマンドも加えたダイスボットの情報の一覧を取得する
# @param [Array<String>] orderedGameNames 順序付けられたゲーム名の配列
# @param [Boolean] showAllDiceBots すべてのダイスボットを表示するか
# @param [Array<Hash>] commandInfos テーブルのコマンドの情報の配列
# @return [Array<Hash>]
#
# このメソッドは、ダイスボットから返された情報を破壊しない。
def self.withTableCommands(orderedGameNames, showAllDiceBots, commandInfos)
diceBotInfos = self.get(orderedGameNames, showAllDiceBots)
# ゲームタイプ => ダイスボット情報のインデックスの対応を作る
diceBotInfoIndexFor = Hash[
diceBotInfos.each_with_index.map { |info, i| [info[KEY_GAME_TYPE], i] }
]
allGameTypes = diceBotInfoIndexFor.keys
# ゲームタイプ => 追加するコマンドの一覧の対応を作る
commandsToAdd = commandInfos.reduce({}) { |acc, commandInfo|
gameType = commandInfo[KEY_GAME_TYPE]
command = commandInfo[KEY_COMMAND]
# ゲームタイプ未指定ならすべてのゲームタイプに追加する
targetGameTypes = gameType.empty? ? allGameTypes : [gameType]
targetGameTypes.each do |targetGameType|
acc[targetGameType] ||= []
acc[targetGameType] << command
end
acc
}
commandsToAdd.each do |gameType, commands|
diceBotInfoIndex = diceBotInfoIndexFor[gameType]
next unless diceBotInfoIndex
originalInfo = diceBotInfos[diceBotInfoIndex]
# ダイスボットから返された情報を破壊しないようにして更新する
diceBotInfos[diceBotInfoIndex] = originalInfo.merge({
KEY_PREFIXS => originalInfo[KEY_PREFIXS] + commands
})
end
diceBotInfos
end
</syntaxhighlight>
== DodontoFServer.rb:サーバ本体 ==
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb
=== L164-L185:<code>@dice_adapter</code> の初期化 ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L164-L185
<syntaxhighlight lang="ruby">
def initialize(saveDirInfo, cgiParams)
@cgiParams = cgiParams
@saveDirInfo = saveDirInfo
@logger = DodontoF::Logger.instance
@cgi = nil
@jsonpCallBack = nil
@isWebIf = false
@isRecordEmpty = false
initSaveFiles(getRequestData('room'))
@dice_adapter = DodontoF::DiceAdapter.new(getDiceBotExtraTableDirName, 'diceBotTable_')
@fullBackupFileBaseName = "DodontoFFullBackup"
@allSaveDataFileExt = '.tar.gz'
@defaultAllSaveData = 'default.sav'
@defaultChatPallete = 'default.cpd'
@card = nil
end
</syntaxhighlight>
<code>getDiceBotExtraTableDirName</code>([https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3727-L3729 L3727-L3729])では、<code>getRoomLocalSpaceDirName</code>([https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3262-L3265 L3262-L3265])、<code>getRoomLocalSpaceDirNameByRoomNo</code>([https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3267-L3273 L3267-L3273])を経由して、<code>$imageUploadDir</code> の中の部屋固有のディレクトリを返す。
=== L1193-L1210:<code>getWebIfServerInfo</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L1193-L1210
Webインターフェースのサーバ情報を返すコマンド。<code>getDiceBotInfos</code> でダイスボットの情報を取得する。
<syntaxhighlight lang="ruby">
def getWebIfServerInfo()
jsonData = {
"maxRoom" => ($saveDataMaxCount - 1),
'isNeedCreatePassword' => (not $createPlayRoomPassword.empty?),
'result' => 'OK',
}
if( getWebIfRequestBoolean("card", false) )
cardInfos = getCardsInfo.collectCardTypeAndTypeName($cardOrder)
jsonData["cardInfos"] = cardInfos
end
if( getWebIfRequestBoolean("dice", false) )
jsonData['diceBotInfos'] = getDiceBotInfos()
end
return jsonData
end
</syntaxhighlight>
=== L2090:<code>getLoginInfo</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L2090
ダイスボット情報の取得を行う。
<syntaxhighlight lang="ruby">
diceBotInfos = getDiceBotInfos()
</syntaxhighlight>
=== L2266-L2280:<code>getDiceBotInfos</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L2266-L2280
ダイスボット情報取得処理の実装。部屋に入っているかどうかで、テーブルのコマンドも含めた情報を返すかどうかを決定している。
<syntaxhighlight lang="ruby">
def getDiceBotInfos
@logger.debug("getDiceBotInfos() Begin")
require 'diceBotInfos'
orderedGameNames = $diceBotOrder.split("\n")
if @saveDirInfo.getSaveDataDirIndex != -1
DiceBotInfos.withTableCommands(orderedGameNames,
$isDisplayAllDice,
@dice_adapter.getGameCommandInfos)
else
DiceBotInfos.get(orderedGameNames, $isDisplayAllDice)
end
end
</syntaxhighlight>
=== L2542-2556:<code>save</code>, <code>getDiceTableData</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L2542-2556
部屋のデータの保存時に、独自の表についての情報を取得する。
<syntaxhighlight lang="ruby">
def save()
isAddPlayRoomInfo = true
extension = @@saveFileExtension
addInfos = {}
addInfos[$diceBotTableSaveKey] = getDiceTableData()
saveSelectFiles($saveFiles.keys, extension, isAddPlayRoomInfo, addInfos)
end
def getDiceTableData()
tableInfos = @dice_adapter.getBotTableInfosFromDir
tableInfos.each{|i| i.delete('fileName') }
return tableInfos
end
</syntaxhighlight>
=== L2806-L2817:<code>getBotTableInfos</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L2806-L2817
独自の表についての情報を取得する。
<syntaxhighlight lang="ruby">
def getBotTableInfos()
@logger.debug("getBotTableInfos Begin")
result = {
"resultText"=> "OK",
}
result["tableInfos"] = @dice_adapter.getBotTableInfosFromDir
@logger.debug(result, "result")
@logger.debug("getBotTableInfos End")
return result
end
</syntaxhighlight>
=== L2819-L2835:<code>addBotTable</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L2819-L2835
独自の表を追加する。
<syntaxhighlight lang="ruby">
def addBotTable()
result = {}
params = getParamsFromRequestData()
result['resultText'] = @dice_adapter.addBotTableMain(params)
if( result['resultText'] != "OK" )
return result
end
@logger.debug("addBotTableMain called")
result = getBotTableInfos()
@logger.debug(result, "addBotTable result")
return result
end
</syntaxhighlight>
=== L2837-L2849:<code>changeBotTable</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L2837-L2849
独自の表を変更する。
<syntaxhighlight lang="ruby">
def changeBotTable()
params = getParamsFromRequestData()
result = {}
result['resultText'] = @dice_adapter.changeBotTableMain(params)
if( result['resultText'] != "OK" )
return result
end
result = getBotTableInfos()
return result
end
</syntaxhighlight>
=== L2851-L2855:<code>removeBotTable</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L2851-L2855
独自の表を削除する。
<syntaxhighlight lang="ruby">
def removeBotTable()
params = getParamsFromRequestData()
@dice_adapter.removeBotTableMain(params)
return getBotTableInfos()
end
</syntaxhighlight>
=== L3458-L3459:<code>loadSaveFileDataFilterByTargets</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3458-L3459
セーブデータの部分読み込み処理の一部。独自の表を読み込む。
<syntaxhighlight lang="ruby">
when "diceBotTable"
loadDiceBotTable(jsonData)
</syntaxhighlight>
=== L3511-L3531:<code>loadDiceBotTable</code>, <code>getDiceBotTableString</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3511-L3531
独自の表を読み込む。
<syntaxhighlight lang="ruby">
def loadDiceBotTable(jsonData)
data = jsonData[$diceBotTableSaveKey]
return if( data.nil? )
data.each do |info|
info['table'] = getDiceBotTableString(info['table'])
@dice_adapter.addBotTableMain(info)
end
end
def getDiceBotTableString(table)
lines = []
table.each do |line|
lines << line.join(":")
end
return lines.join("\n")
end
</syntaxhighlight>
=== L3632-L3657:<code>sendDiceBotChatMessage</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3632-L3657
BCDiceにコマンドを送る処理。<code>回数 コマンド</code> という形で送信回数が指定されていた場合は、指定された回数だけコマンドをBCDiceに送る。
<syntaxhighlight lang="ruby">
def sendDiceBotChatMessage
@logger.debug('sendDiceBotChatMessage')
params = getParamsFromRequestData()
repeatCount = getDiceBotRepeatCount(params)
results = []
repeatCount.times do |i|
paramsClone = params.clone
paramsClone['message'] += " \##{ i + 1 }" if( repeatCount > 1 )
result = sendDiceBotChatMessageOnece( paramsClone )
@logger.debug(result, "sendDiceBotChatMessageOnece result")
next if( result.nil? )
results << result
end
@logger.debug(results, "sendDiceBotChatMessage results")
return results
end
</syntaxhighlight>
=== L3659-L3669:<code>getDiceBotRepeatCount</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3659-L3669
コマンド送信回数を1〜20回に制限する。最近のRubyでは <code>(params['repeatCount'] || 1).clamp(1, 20)</code> と簡潔に書ける。
<syntaxhighlight lang="ruby">
def getDiceBotRepeatCount(params)
repeatCountLimit = 20
repeatCount = params['repeatCount']
repeatCount ||= 1
repeatCount = 1 if( repeatCount < 1 )
repeatCount = repeatCountLimit if( repeatCount > repeatCountLimit )
return repeatCount
end
</syntaxhighlight>
=== L3672-L3709:<code>sendDiceBotChatMessageOnece</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3672-L3709
BCDiceに1回分(おそらく <code>Onece</code> は <code>once</code> のスペルミス)のコマンドを送る処理。<code>getRollDiceResult</code> でダイスロールした結果を取得する。<code>sendChatMessageByChatData</code>([https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3817-3839 L3817-3839])で、その結果を含むメッセージを送信する。
<syntaxhighlight lang="ruby">
def sendDiceBotChatMessageOnece(params)
rolledMessage, isSecret, secretMessage = getRollDiceResult( params )
senderName = params['name']
unless /\t/ === senderName
state = params['state']
senderName += ("\t" + state) unless( state.empty? )
end
chatData = {
"senderName" => senderName,
"message" => rolledMessage,
"color" => params['color'],
"uniqueId" => '0',
"channel" => params['channel']
}
sendto = params['sendto']
unless( sendto.nil? )
chatData['sendto'] = sendto
chatData['sendtoName'] = sendtoName
end
@logger.debug(chatData, 'sendDiceBotChatMessageOnece chatData')
sendChatMessageByChatData(chatData)
result = nil
if( isSecret )
params['isSecret'] = isSecret
params['message'] = secretMessage
result = params
end
return result
end
</syntaxhighlight>
=== L3672-L3725:<code>getRollDiceResult</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3672-L3709
BCDiceでダイスを振る。シークレットダイスかどうかも考慮してメッセージを加工し、返す。
<syntaxhighlight lang="ruby">
def getRollDiceResult( params )
params['originalMessage'] = params['message']
rollResult, isSecret, randResults = @dice_adapter.rollDice(params)
secretMessage = ""
if( isSecret )
secretMessage = params['message'] + rollResult
else
params['message'] += rollResult
end
rolledMessage = getRolledMessage(params, isSecret, randResults)
return rolledMessage, isSecret, secretMessage
end
</syntaxhighlight>
=== L3732-L3762:<code>getRolledMessage</code> ===
https://github.com/torgtaitai/DodontoF/blob/d3e4cc374885986efc761cfabbb19e4b35e815e0/DodontoFServer.rb#L3732-L3709
ダイスロールの結果を入力として、どどんとふクライアントでの表示に必要な情報を付加する。シークレットダイスの場合に結果を隠すことと、「!」の数でサイコロを強調できるようにすることが目的のようだ。
<syntaxhighlight lang="ruby">
def getRolledMessage(params, isSecret, randResults)
@logger.debug("getRolledMessage Begin")
@logger.debug(isSecret, "isSecret")
@logger.debug(randResults, "randResults")
if( isSecret )
params['message'] = getLanguageKey('secretDice')
randResults = randResults.collect{|value, max| [0, 0] }
end
message = params['message']
if( randResults.nil? )
@logger.debug("randResults is nil")
return message
end
data = {
"chatMessage" => message,
"randResults" => randResults,
"uniqueId" => params['uniqueId'],
"power" => getDiceBotPower(params),
}
text = "###CutInCommand:rollVisualDice###" + getJsonString(data)
@logger.debug(text, "getRolledMessage End text")
return text
end
</syntaxhighlight>
[[Category:BCDice/TRPGツールからの呼び出し方]]
{{DEFAULTSORT:ととんとふ}}