维护提醒
BWIKI 全站将于 9 月 3 日(全天)进行维护,期间无法编辑任何页面或发布新的评论。
全站通知:
模块:Mail
刷
历
编
跳到导航
跳到搜索
local Helper = require("Module:Helper")
local ItemNames = require("Module:ItemNames")
local Quests = require("Module:Quests")
local MailData = Helper.LazyLoad('Module:Mail/data')
local p = {}
-- 清理文本,处理换行符和玩家名称占位符
local function cleanText(text)
if not text then return "" end
-- 处理换行符
text = text:gsub("%^", "\n")
-- 处理玩家名称占位符
text = text:gsub("@", Helper.ExpandTemplate("玩家", {}))
return text
end
-- 获取物品显示名称(参考Dialogue.lua中的getItemDisplayName)
local function getItemDisplayName(itemId, count)
local templateArgs = {}
if itemId == "(O)126" or itemId == "126" then
templateArgs[1] = "Strange Doll (green)"
elseif itemId == "(O)127" or itemId == "127" then
templateArgs[1] = "Strange Doll (yellow)"
else
local chineseName = ItemNames.getEnglishName(itemId)
if chineseName and chineseName ~= "" then
templateArgs[1] = chineseName
else
return nil
end
end
-- 如果存在数量且大于1,将数量作为第二个参数传递
if count and count > 1 then
templateArgs[2] = tostring(count)
end
templateArgs.class = "inline"
return Helper.ExpandTemplate("Name", templateArgs)
end
-- 中文物品拼接逻辑
local function joinItems(items)
if not items or #items == 0 then
return ""
elseif #items == 1 then
return items[1]
elseif #items == 2 then
-- 两个时:A或B
return items[1] .. "或" .. items[2]
else
-- 三个或以上时:A、B或C / A、B、C或D
local result = ""
for i = 1, #items - 2 do
result = result .. items[i] .. "、"
end
result = result .. items[#items - 1] .. "或" .. items[#items]
return result
end
end
-- 解析信件内容,分离标题、内容和物品信息
local function parseMailContent(mailText, recipeParam)
if not mailText then return nil, nil, nil end
-- 分离标题部分 [#]标题
local content, title = mailText:match("^(.*)%[#%](.*)$")
if not content then
content = mailText
title = ""
end
-- 解析物品信息
local items = {}
local cleanContent = content
-- 处理 %item 命令
cleanContent = cleanContent:gsub("%%item%s+([^%%]+)%%%%", function(itemCommand)
local parts = {}
for part in itemCommand:gmatch("%S+") do
table.insert(parts, part)
end
if #parts >= 1 then
local itemType = parts[1]
if itemType == "id" then
-- %item id (O)388 50 %%
local i = 2
while i <= #parts do
if parts[i] and parts[i+1] then
table.insert(items, {
type = "item",
id = parts[i],
count = tonumber(parts[i+1]) or 1
})
i = i + 2
else
break
end
end
elseif itemType == "money" then
-- %item money 500 501 %%
if parts[2] and parts[3] then
local min = tonumber(parts[2]) or 0
local max = tonumber(parts[3]) or min
table.insert(items, {
type = "money",
amount = min -- 使用最小值作为金币数量
})
elseif parts[2] then
local amount = tonumber(parts[2]) or 0
table.insert(items, {
type = "money",
amount = amount
})
end
elseif itemType == "cookingRecipe" then
-- %item cookingRecipe %%
table.insert(items, {
type = "cookingRecipe",
recipe = recipeParam or "unknown"
})
elseif itemType == "craftingRecipe" then
-- %item craftingRecipe Tea_Sapling %%
table.insert(items, {
type = "craftingRecipe",
recipe = parts[2] or "unknown"
})
elseif itemType == "quest" then
-- %item quest 1 true %%
table.insert(items, {
type = "quest",
questId = parts[2] or "unknown",
auto = parts[3] == "true"
})
elseif itemType == "conversationTopic" then
-- %item conversationTopic ElliottGone2 0 %%
table.insert(items, {
type = "conversationTopic",
topic = parts[2] or "unknown",
days = tonumber(parts[3]) or 0
})
elseif itemType == "itemRecovery" then
-- %item itemRecovery %%
table.insert(items, {
type = "itemRecovery"
})
end
end
return "" -- 移除物品命令文本
end)
-- 处理旧版物品命令
cleanContent = cleanContent:gsub("%%item%s+object%s+([^%%]+)%%%%", function(objectCommand)
local parts = {}
for part in objectCommand:gmatch("%S+") do
table.insert(parts, part)
end
local i = 1
while i <= #parts do
if parts[i] and parts[i+1] then
table.insert(items, {
type = "item",
id = "(O)" .. parts[i],
count = tonumber(parts[i+1]) or 1
})
i = i + 2
else
break
end
end
return ""
end)
cleanContent = cleanContent:gsub("%%item%s+bigobject%s+([^%%]+)%%%%", function(bigObjectCommand)
local parts = {}
for part in bigObjectCommand:gmatch("%S+") do
table.insert(parts, part)
end
for _, id in ipairs(parts) do
table.insert(items, {
type = "item",
id = "(BC)" .. id,
count = 1
})
end
return ""
end)
cleanContent = cleanContent:gsub("%%item%s+furniture%s+([^%%]+)%%%%", function(furnitureCommand)
local parts = {}
for part in furnitureCommand:gmatch("%S+") do
table.insert(parts, part)
end
for _, id in ipairs(parts) do
table.insert(items, {
type = "item",
id = "(F)" .. id,
count = 1
})
end
return ""
end)
-- 清理多余的空白
cleanContent = cleanContent:gsub("%s+", " ")
cleanContent = cleanContent:gsub("^%s+", "")
cleanContent = cleanContent:gsub("%s+$", "")
return cleanText(cleanContent), cleanText(title), items
end
-- 获取信件的标题
function p.getTitle(frame)
local mailId = frame.args[1]
if not mailId then
return "错误:未提供信件ID"
end
local mailText = MailData[mailId]
if not mailText then
return "错误:未找到信件 " .. mailId
end
local recipeParam = frame.args.recipe
local _, title, _ = parseMailContent(mailText, recipeParam)
return title or ""
end
-- 获取信件的内容
function p.getContent(frame)
local mailId = frame.args[1]
if not mailId then
return "错误:未提供信件ID"
end
local mailText = MailData[mailId]
if not mailText then
return "错误:未找到信件 " .. mailId
end
local recipeParam = frame.args.recipe
local content, _, _ = parseMailContent(mailText, recipeParam)
return content or ""
end
-- 获取信件的物品信息
function p.getItems(frame)
local mailId = frame.args[1]
if not mailId then
return "错误:未提供信件ID"
end
local mailText = MailData[mailId]
if not mailText then
return "错误:未找到信件 " .. mailId
end
local recipeParam = frame.args.recipe
local _, _, items = parseMailContent(mailText, recipeParam)
if not items or #items == 0 then
return ""
end
local result = {}
for _, item in ipairs(items) do
if item.type == "item" then
-- 6. 如果是普通物品,获取各个物品的名称,然后通过Name模板展开
local displayName = getItemDisplayName(item.id, item.count)
if displayName then
table.insert(result, displayName)
else
local itemText = item.id
if item.count and item.count > 1 then
itemText = itemText .. " x" .. item.count
end
table.insert(result, itemText)
end
elseif item.type == "money" then
-- 2. 如果是金币,金币数量视为参数一,使用模板price展开
table.insert(result, Helper.ExpandTemplate("price", {tostring(item.amount)}))
elseif item.type == "cookingRecipe" then
-- 4. 如果是烹饪配方,检查传入的参数中是否有recipe=xxx
if item.recipe and item.recipe ~= "unknown" then
table.insert(result, Helper.ExpandTemplate("Recipe", {item.recipe, "36", "center"}))
else
table.insert(result, "<!-- 烹饪配方 -->")
end
elseif item.type == "craftingRecipe" then
-- 3. 如果是制作配方,将配方名称的下划线替换为空格,然后使用模板Recipe展开
local recipeName = item.recipe:gsub("_", " ")
table.insert(result, Helper.ExpandTemplate("Recipe", {recipeName, "36", "center"}))
elseif item.type == "quest" then
-- 5. 如果是任务,联动Quests.lua输出任务的简要信息
local questName = Quests.getQuestName({args = {item.questId}})
local questDesc = Quests.getQuestDescription({args = {item.questId}})
if questName and questName ~= "" then
table.insert(result, questName .. (questDesc and questDesc ~= "" and (":" .. questDesc) or ""))
else
table.insert(result, "任务:" .. item.questId .. (item.auto and "(自动接受)" or ""))
end
elseif item.type == "conversationTopic" then
-- 1. 如果是对话话题,那么把它用<!-- -->进行包裹(视作注释)
table.insert(result, "<!-- 对话话题:" .. item.topic .. "(" .. item.days .. "天)-->")
elseif item.type == "itemRecovery" then
table.insert(result, "失物招领")
end
end
return joinItems(result)
end
-- 同时获取信件的标题、内容、物品
function p.getAll(frame)
local mailId = frame.args[1]
if not mailId then
return "错误:未提供信件ID"
end
local mailText = MailData[mailId]
if not mailText then
return "错误:未找到信件 " .. mailId
end
local recipeParam = frame.args.recipe
local content, title, items = parseMailContent(mailText, recipeParam)
local result = {}
-- 标题
if title and title ~= "" then
table.insert(result, "'''标题:'''" .. title)
end
-- 内容
if content and content ~= "" then
table.insert(result, "'''内容:'''\n" .. content)
end
-- 物品
if items and #items > 0 then
local itemTexts = {}
for _, item in ipairs(items) do
if item.type == "item" then
-- 6. 如果是普通物品,获取各个物品的名称,然后通过Name模板展开
local displayName = getItemDisplayName(item.id, item.count)
if displayName then
table.insert(itemTexts, displayName)
else
local itemText = item.id
if item.count and item.count > 1 then
itemText = itemText .. " x" .. item.count
end
table.insert(itemTexts, itemText)
end
elseif item.type == "money" then
-- 2. 如果是金币,金币数量视为参数一,使用模板price展开
table.insert(itemTexts, Helper.ExpandTemplate("price", {tostring(item.amount)}))
elseif item.type == "cookingRecipe" then
-- 4. 如果是烹饪配方,检查传入的参数中是否有recipe=xxx
if item.recipe and item.recipe ~= "unknown" then
table.insert(itemTexts, Helper.ExpandTemplate("Recipe", {item.recipe, "36", "center"}))
else
table.insert(itemTexts, "<!-- 烹饪配方 -->")
end
elseif item.type == "craftingRecipe" then
-- 3. 如果是制作配方,将配方名称的下划线替换为空格,然后使用模板Recipe展开
local recipeName = item.recipe:gsub("_", " ")
table.insert(itemTexts, Helper.ExpandTemplate("Recipe", {recipeName, "36", "center"}))
elseif item.type == "quest" then
-- 5. 如果是任务,联动Quests.lua输出任务的简要信息
local questName = Quests.getQuestName({args = {item.questId}})
local questDesc = Quests.getQuestDescription({args = {item.questId}})
if questName and questName ~= "" then
table.insert(itemTexts, questName .. (questDesc and questDesc ~= "" and (":" .. questDesc) or ""))
else
table.insert(itemTexts, "任务:" .. item.questId .. (item.auto and "(自动接受)" or ""))
end
elseif item.type == "conversationTopic" then
-- 1. 如果是对话话题,那么把它用<!-- -->进行包裹(视作注释)
table.insert(itemTexts, "<!-- 对话话题:" .. item.topic .. "(" .. item.days .. "天)-->")
elseif item.type == "itemRecovery" then
table.insert(itemTexts, "失物招领")
end
end
if #itemTexts > 0 then
table.insert(result, "'''物品:'''" .. joinItems(itemTexts))
end
end
return table.concat(result, "\n\n")
end
-- 设置信件变量(不输出内容)
function p.setVars(frame)
local mailId = frame.args[1]
if not mailId then
return ""
end
local mailText = MailData[mailId]
if not mailText then
return ""
end
local recipeParam = frame.args.recipe
local content, title, items = parseMailContent(mailText, recipeParam)
-- 设置标题变量
if title and title ~= "" then
frame:callParserFunction('#vardefine', {'letter_title', title})
end
-- 设置内容变量
if content and content ~= "" then
frame:callParserFunction('#vardefine', {'letter_content', content:gsub('\n', '\n\n')})
end
-- 设置物品变量
if items and #items > 0 then
local itemTexts = {}
for _, item in ipairs(items) do
if item.type == "item" then
-- 6. 如果是普通物品,获取各个物品的名称,然后通过Name模板展开
local displayName = getItemDisplayName(item.id, item.count)
if displayName then
table.insert(itemTexts, displayName)
else
local itemText = item.id
if item.count and item.count > 1 then
itemText = itemText .. " x" .. item.count
end
table.insert(itemTexts, itemText)
end
elseif item.type == "money" then
-- 2. 如果是金币,金币数量视为参数一,使用模板price展开
table.insert(itemTexts, Helper.ExpandTemplate("price", {tostring(item.amount)}))
elseif item.type == "cookingRecipe" then
-- 4. 如果是烹饪配方,检查传入的参数中是否有recipe=xxx
if item.recipe and item.recipe ~= "unknown" then
table.insert(itemTexts, Helper.ExpandTemplate("Recipe", {item.recipe, "36", "center"}))
else
table.insert(itemTexts, "<!-- 烹饪配方 -->")
end
elseif item.type == "craftingRecipe" then
-- 3. 如果是制作配方,将配方名称的下划线替换为空格,然后使用模板Recipe展开
local recipeName = item.recipe:gsub("_", " ")
table.insert(itemTexts, Helper.ExpandTemplate("Recipe", {recipeName, "36", "center"}))
elseif item.type == "quest" then
-- 5. 如果是任务,联动Quests.lua输出任务的简要信息
local questName = Quests.getQuestName({args = {item.questId}})
local questDesc = Quests.getQuestDescription({args = {item.questId}})
if questName and questName ~= "" then
table.insert(itemTexts, questName .. (questDesc and questDesc ~= "" and (":" .. questDesc) or ""))
else
table.insert(itemTexts, "任务:" .. item.questId .. (item.auto and "(自动接受)" or ""))
end
elseif item.type == "conversationTopic" then
-- 1. 如果是对话话题,那么把它用<!-- -->进行包裹(视作注释)
table.insert(itemTexts, "<!-- 对话话题:" .. item.topic .. "(" .. item.days .. "天)-->")
elseif item.type == "itemRecovery" then
table.insert(itemTexts, "失物招领")
end
end
if #itemTexts > 0 then
frame:callParserFunction('#vardefine', {'letter_receive', joinItems(itemTexts)})
end
end
-- 不输出任何内容
return ""
end
p.debug = function ()
return p.getAll{ args={"Shane"} } -- elliottLetter1
end
return p