维护提醒

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