From 1308079fba1e1cc49640349f79b1241510b3e734 Mon Sep 17 00:00:00 2001 From: tastybento Date: Wed, 29 Jul 2026 09:07:36 -0700 Subject: [PATCH 01/15] ci: bump publish-platforms pin to the multipart-JSON fix The pinned SHA predates BentoBoxWorld/.github#13, which moved the CurseForge metadata and Hangar versionUpload JSON out of inline curl -F values and into files. curl treats a ';' in an inline -F value as the start of a type= attribute, so a release body containing a semicolon truncates the JSON and both platforms reject the upload. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01SAQ3YQkcfRoCZEwa6SPJcp --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 238d043e..93323585 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -18,7 +18,7 @@ on: jobs: publish: - uses: bentoboxworld/.github/.github/workflows/publish-platforms.yml@ca2dcd167e8db4e0f671a976080744dda43801a6 # master + uses: bentoboxworld/.github/.github/workflows/publish-platforms.yml@1f91a0edf72e8c86d671b3b8fdd3121ac6fb88e1 # master with: use_release_asset: "true" # publish the jar attached to the release; do not rebuild hangar_slug: "Challenges-For-BentoBox" # blank = skip Hangar From bce9a9725dd04321ee3d9c8a29001f05d466e104 Mon Sep 17 00:00:00 2001 From: qwe664 <93234700+qwe664@users.noreply.github.com> Date: Mon, 3 Aug 2026 08:26:13 +0800 Subject: [PATCH 02/15] Improve Traditional Chinese (zh-TW) translation --- src/main/resources/locales/zh-TW.yml | 1899 ++++++++++++++------------ 1 file changed, 993 insertions(+), 906 deletions(-) diff --git a/src/main/resources/locales/zh-TW.yml b/src/main/resources/locales/zh-TW.yml index 0795560a..df653b58 100644 --- a/src/main/resources/locales/zh-TW.yml +++ b/src/main/resources/locales/zh-TW.yml @@ -1,1252 +1,1339 @@ ---- -########################################################################################### +# ########################################################################################## # This is a YML file. Be careful when editing. Check your edits in a YAML checker like # # the one at http://yaml-online-parser.appspot.com # -########################################################################################### +# ########################################################################################## -### Credits ### meta: - authors: [] + authors: + - BONNe challenges: + materials: + any: '任何' + all_hanging_signs: + name: 任何懸掛式告示牌 + all_signs: + name: 任何告示牌 + commands: admin: main: parameters: '' - description: '打開管理員菜單' - import: - description: '從challenges.yml文件中導入挑戰以及挑戰等級' - parameters: '[overwrite]' + description: 主要管理員指令。開啟介面。 reload: - description: '重載挑戰組件' - parameters: '[hard]' - show: - description: '在聊天中列出當前世界的所有挑戰' + description: 從資料庫重新載入挑戰資料。 parameters: '' - defaults: - description: '顯示導入/導出插件自帶挑戰的子指令' - parameters: '[command]' - defaults-import: - description: '導入插件自帶挑戰' + show: + description: 在聊天室中顯示此世界的所有挑戰。 parameters: '' - defaults-generate: - description: '將現有的挑戰導出到default.json文件中。' - parameters: '[overwrite] - allows to overwrite existing file.' complete: - description: '通過指令讓某個玩家完成指定挑戰' - parameters: ' ' + description: 為玩家完成一項挑戰。 + parameters: reset: - description: 重設玩家的挑戰。若「challenge_id」設定為「all」,則所有挑戰都會被重設。 + description: 重設玩家的一項挑戰。若「challenge_id」設為「all」,則會重設所有挑戰。 parameters: migrate: - description: 將當前遊戲世界的挑戰資料遷移至 0.8.0 儲存格式。 + description: 將目前遊戲世界的挑戰資料遷移至 0.8.0 儲存格式。 parameters: '' user: main: - description: '打開空島挑戰菜單' + description: 開啟挑戰介面。 parameters: '' complete: - description: '通過指令完成挑戰' - parameters: ' [count]' + description: 完成一項挑戰。 + parameters: [count] gui: - title: - admin: - gui-title: '島嶼挑戰管理' - edit-challenge-title: '編輯挑戰' - edit-level-title: '編輯挑戰等級' - settings-title: '編輯設定' - choose-challenge-title: '選擇挑戰' - choose-level-title: '選擇挑戰等級' - choose-user-title: '選擇玩家' - manage-blocks: '管理方塊' - manage-entities: '管理實體' - confirm-title: '確認' - manage-items: '管理物品' - manage-numbers: '數字墊' - select-block: '選擇方塊' - select-challenge: '選擇挑戰' - select-entity: '選擇實體' - toggle-environment: '切換環境' - edit-text-fields: '編輯文本字段' - challenges: '島嶼挑戰' - game-modes: '選擇游戲模式' + titles: + # The title for the Main GUI + player-gui: 挑戰選單 + # The title for the Main GUI + gamemode-gui: 選擇遊戲模式 + # The title for the Multiple Completion GUI + multiple-gui: 要完成幾次? + # GUI titles below are visible just for Admins. + admin-gui: 挑戰管理選單 + edit-challenge: 編輯 [challenge] + edit-level: 編輯 [level] + settings: 設定 + choose-challenge: 選擇挑戰 + choose-level: 選擇等級 + choose-player: 選擇玩家 + library: 圖書館 + manage-blocks: 管理方塊 + manage-block-groups: 管理方塊群組 + manage-entity-groups: 管理實體群組 + manage-entities: 管理實體 + manage-statistics: 管理統計資料 + manage-advancements: 管理進度 + advancement-selector: 進度選擇器 + type-selector: 挑戰類型選擇器 + item-selector: 物品選擇器 + block-selector: 方塊選擇器 + entity-selector: 實體選擇器 + challenge-selector: 挑戰選擇器 + statistic-selector: 統計資料選擇器 + environment-selector: 維度選擇器 buttons: - admin: - complete: '完成某個玩家的挑戰' - reset: '重置某個玩家的挑戰' - create-challenge: '創建新的挑戰' - create-level: '創建新的挑戰等級' - edit-challenge: '編輯挑戰' - edit-level: '編輯挑戰等級' - delete-challenge: '删除挑戰' - delete-level: '删除挑戰等級' - import: '導入ASkyBlock插件的挑戰內容' - settings: '編輯設定' - properties: '屬性' - requirements: '要求' - rewards: '獎勵' - challenges: '挑戰' - type: '挑戰類型' - deployment: '是否開啓該挑戰' - icon: '圖標' - locked-icon: '圖標鎖' - description: '介紹' - order: '順序' - environment: '環境' - remove-on-complete: '完成後删除該挑戰' - name: '挑戰名稱' - required-entities: '檢測的實體' - remove-entities: '完成任務後是否殺死實體' - required-blocks: '檢測的方塊' - remove-blocks: '完成任務後是否删除方塊' - search-radius: '搜索半徑' - required-permissions: '需要的權限' - required-items: '需要的物品' - remove-items: '完成任務後是否删除物品' - required-experience: '需要的經驗值' - remove-experience: '完成任務後是否删除經驗值' - required-level: '需要的島嶼等級' - required-money: '需要的金錢' - remove-money: '完成任務後是否删除金錢' - reward-text: '獎勵信息' - reward-items: '物品獎勵' - reward-experience: '經驗獎勵' - reward-money: '金錢獎勵' - reward-commands: '指令獎勵' - repeatable: '是否可重複挑戰' - repeat-count: '最大時間' - repeat-reward-text: '重複獎勵信息' - repeat-reward-items: '重複物品獎勵' - repeat-reward-experience: '重複經驗獎勵' - repeat-reward-money: '重複金錢獎勵' - repeat-reward-commands: '重複指令獎勵' - waiver-amount: '豁免金額' - add-challenge: '添加挑戰' - remove-challenge: '删除挑戰' - reset-on-new: '在新的島嶼上重置' - broadcast: '成功任務後發出廣播' - remove-completed: '完成任務後删除圖標' - glow: '完成任務後發光' - free-at-top: '免費挑戰優先排列' - line-length: 'Lore長度' - toggle-user-list: '用戶列表' - remove-selected: '删除選定' - add: '添加' - show-eggs: '切換視圖模式' - accept: '接受' - decline: '拒絕' - save: '保存' - cancel: '取消' - input: '輸入' - value: '值' - set: '=' - increase: '+' - reduce: '-' - multiply: '*' - clear: '清空' - remove-empty: '删除空欄' - number: '[number]' - level-lore: '等級介紹' - challenge-lore: '挑戰介紹' - gui-view-mode: '顯示所有GameModes' - gui-mode: '挑戰GUI' - history-store: '挑戰歷史' - history-lifespan: '歷史LifeSpan' - island-store: '每個島嶼的商店' - default-locked-icon: '等級圖標鎖' - input-mode: '切換輸入模式' - title-enable: '顯示標題' - title-showtime: '標題顯示時間' - default-import: '導入默認挑戰' - default-export: '導出現有挑戰' - complete-wipe: '抹除插件數據庫!' - next: - name: 下一頁 - description: 切換至第 [number] 頁 + # Button in the Challenges GUI that allows to select free challenges. + free-challenges: + name: 自由挑戰 + description: |- + 顯示所有 + 自由挑戰 +# Button that is used to return to previous GUI or exit it completely. + return: + name: 返回 + description: |- + 返回上一個選單 + 或離開選單 +# Button that is used in multi-page GUIs which allows to return to previous page. previous: name: 上一頁 description: 切換至第 [number] 頁 - return: - name: 返回 - description: "返回上一個選單\n或退出 GUI" - free-challenges: - name: 自由挑戰 - description: "顯示\n自由挑戰清單" +# Button that is used in multi-page GUIs which allows to go to next page. + next: + name: 下一頁 + description: 切換至第 [number] 頁 +# Button that allows to reduce number reduce: name: 減少 description: 減少 [number] +# Button that allows to increase number increase: name: 增加 description: 增加 [number] +# Button that displays and allows completing challenge accept: name: 完成 - description: "完成挑戰 [number]\n次" + description: |- + 完成挑戰 + [number] 次 +# Button that allows to quit the current gui. quit: - name: 退出 - description: 退出 GUI。 + name: 離開 + description: 離開選單。 +# All following buttons are mainly for Admin GUI. complete_user_challenges: - name: 完成玩家挑戰(-s) - description: "允許你選擇一位玩家\n並完成他們的挑戰。" + name: 完成玩家挑戰 + description: |- + 選擇一位玩家, + 並替其完成挑戰。 reset_user_challenges: name: 重設玩家挑戰 - description: "允許你選擇一位玩家\n並重設他們的挑戰。" + description: |- + 選擇一位玩家, + 並重設其挑戰。 add_challenge: name: 建立挑戰 - description: "開始建立\n新挑戰的流程。" + description: |- + 開始建立 + 新的挑戰。 add_level: name: 建立等級 - description: "開始建立\n新等級的流程。" + description: |- + 開始建立 + 新的等級。 edit_challenge: name: 編輯挑戰 - description: "允許你選擇並編輯\n挑戰。" + description: |- + 選擇並編輯 + 一項挑戰。 edit_level: name: 編輯等級 - description: "允許你選擇並編輯\n等級。" + description: |- + 選擇並編輯 + 一個等級。 delete_challenge: name: 刪除挑戰 - description: "允許你選擇並刪除\n挑戰。" + description: |- + 選擇並刪除 + 一項挑戰。 delete_level: name: 刪除等級 - description: "允許你選擇並刪除\n等級。" + description: |- + 選擇並刪除 + 一個等級。 edit_settings: name: 設定 - description: "允許你查看及編輯\n附加元件設定。" + description: |- + 檢視並編輯 + 附加元件設定。 complete_wipe: name: 完全清除 - description: "完全清除挑戰\n附加元件資料庫,包括\n玩家資料。" + description: |- + 完整清除挑戰 + 附加元件資料庫, + 包含所有玩家資料。 challenge_wipe: - name: 挑戰清除 - description: "完全清除挑戰\n和等級資料庫。" + name: 清除挑戰資料 + description: |- + 完整清除資料庫中的 + 所有挑戰與等級。 user_wipe: - name: 玩家清除 - description: "完全清除玩家\n資料庫中的資料。" + name: 清除玩家資料 + description: |- + 完整清除資料庫中的 + 所有玩家資料。 library: name: 圖書館 - description: "開啟公開的\n挑戰圖書館。" - downloading: "圖書館下載\n已要求..." + description: |- + 開啟公開的 + 挑戰圖書館。 + downloading: |- + 已提出下載 + 圖書館請求…… import_database: name: 匯入資料庫 - description: "允許你匯入已匯出的\n挑戰資料庫。" + description: |- + 匯入已匯出的 + 挑戰資料庫。 import_template: - name: 匯入樣板 - description: "允許你匯入包含\n挑戰的樣板檔案。" + name: 匯入範本 + description: |- + 匯入包含挑戰的 + 範本檔案。 export_challenges: name: 匯出挑戰 - description: "允許你將資料庫\n匯出至本機檔案。" + description: |- + 將資料庫匯出至 + 本機檔案。 properties: name: 屬性 - description: 查看所有主要屬性。 + description: 檢視所有主要屬性。 requirements: - name: 需求 - description: 查看需求屬性。 + name: 需求條件 + description: 檢視需求條件屬性。 rewards: name: 獎勵 - description: 查看獎勵屬性。 + description: 檢視獎勵屬性。 hide_reward_items: name: 隱藏獎勵物品 - description: "切換獎勵物品是否\n在 GUI 中顯示。" + description: |- + 切換是否在選單中 + 顯示獎勵物品。 hide: 隱藏 show: 顯示 deployed: name: 部署 - description: "切換挑戰是否\n已部署並可由\n玩家完成。" + description: |- + 切換此挑戰是否已部署, + 並允許玩家 + 完成。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 name: name: 名稱 - description: "允許你變更\n顯示名稱。" - value: 目前為:[name] + description: |- + 允許你變更 + 顯示名稱。 + value: '目前:[name]' remove_on_complete: name: 完成後隱藏 - description: "切換挑戰是否應該\n在玩家完成後\n對其隱藏。" + description: |- + 切換玩家完成挑戰後, + 是否將此挑戰 + 隱藏。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 team_challenge: name: 團隊挑戰 - description: "切換這是否為團隊挑戰。\n團隊挑戰需要一個團隊並在整個島嶼\n共享完成和冷卻時間。" + description: |- + 切換此挑戰是否為團隊挑戰。 + 團隊挑戰需要有隊伍, + 並於整座島嶼共用完成狀態與冷卻時間。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 team_presence: - name: 團隊成員在線 - description: "必須在線的團隊百分比\n以完成此挑戰。\n0 會禁用成員限制。" - value: 目前為:[number]% + name: 團隊在線率 + description: |- + 完成此挑戰時, + 隊伍中必須在線的 + 成員百分比。 + 設為 0 可停用此限制。 + value: '目前:[number]%' aggregate_team: - name: 跨團隊彙總 - description: "將必需的物品/統計資料彙總為\n所有在線成員(共同貢獻,\n合力努力)。" + name: 團隊合併計算 + description: |- + 將所有在線成員的 + 需求物品/統計資料合併計算 + (共同貢獻、共同努力)。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 per_member: - name: 每個成員付款 - description: "每個在線成員必須貢獻他們的\n份額(所需數量是團隊\n總數,分配給現有成員)。" + name: 每位成員皆需貢獻 + description: |- + 每位在線成員都必須繳交 + 自己的份額(需求數量為 + 團隊總需求,平均分配給在線成員)。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 hide_if_no_team: - name: 沒有團隊時隱藏 - description: "若已啟用,此挑戰完全隱藏\n在沒有團隊的玩家。\n若已禁用,則顯示但停用。" + name: 無隊伍時隱藏 + description: |- + 啟用後,沒有隊伍的玩家 + 將完全看不到此挑戰。 + 停用後則仍會顯示,但無法完成。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 description: name: 描述 - description: "指定挑戰的描述。\n必須對其套用顏色代碼。" - value: 目前描述: + description: |- + 設定此挑戰的描述。 + 需自行加入色彩代碼。 + value: '目前描述:' environment: name: 維度 - description: "允許你將挑戰限制\n於特定維度。" + description: |- + 允許你將此挑戰 + 限制於指定維度。 enabled: disabled: order: - name: 順序 - description: "允許你變更\n物件的順序。\n具有相同編號的物件\n將按其\n唯一 ID 名稱排序。" - value: 目前順序:[number] + name: 排序 + description: |- + 允許你調整 + 物件的排序順序。 + 若排序值相同, + 則依照其 + 唯一 ID 名稱排序。 + value: '目前排序:[number]' icon: name: 圖示 - description: "允許你變更此挑戰\n的圖示。" + description: |- + 允許你變更 + 此挑戰的圖示。 locked_icon: name: 鎖定圖示 - description: "允許你變更鎖定\n等級圖示。" + description: |- + 允許你變更 + 鎖定狀態的等級圖示。 required_permissions: - name: 所需權限 - description: "允許你變更此挑戰\n所需的權限以\n完成。" - title: 權限: + name: 需求權限 + description: |- + 允許你修改 + 完成此挑戰 + 所需的權限。 + title: '權限:' permission: ' - [permission]' - none: 未設定權限。 + none: 尚未設定任何權限。 remove_entities: name: 移除實體 - description: "切換所需實體是否將\n在完成挑戰後\n從世界移除。" + description: |- + 切換完成挑戰後, + 是否將所需實體 + 自世界中移除。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 required_entities: - name: 所需實體 - description: "允許你變更此挑戰\n所需的實體以\n完成。" - title: 實體: + name: 需求實體 + description: |- + 允許你修改 + 完成此挑戰 + 所需的實體。 + title: '實體:' list: ' - [number] x [entity]' - none: 未新增任何實體。 + none: 尚未新增任何實體。 remove_blocks: name: 移除方塊 - description: "切換所需方塊是否將\n在完成挑戰後\n從世界移除。" + description: |- + 切換完成挑戰後, + 是否將所需方塊 + 自世界中移除。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 required_blocks: - name: 所需方塊 - description: "允許你變更此挑戰\n所需的方塊以\n完成。" - title: 方塊: + name: 需求方塊 + description: |- + 允許你修改 + 完成此挑戰 + 所需的方塊。 + title: '方塊:' list: ' - [number] x [block]' - none: 未新增任何方塊。 + none: 尚未新增任何方塊。 required_statistics: - name: 所需統計資料 - description: "允許你變更此挑戰\n所需的統計資料以\n完成。" - title: 統計資料: + name: 需求統計資料 + description: |- + 允許你修改 + 完成此挑戰 + 所需的統計資料。 + title: '統計資料:' list: ' - [name]' - none: 未新增任何統計資料。 + none: 尚未新增任何統計資料。 required_advancements: - name: 所需進度 - description: "允許你變更此挑戰\n所需的進度以\n完成。" - title: 進度: + name: 需求進度 + description: |- + 允許你修改 + 完成此挑戰 + 所需的進度。 + title: '進度:' list: ' - [name]' - none: 未新增任何進度。 + none: 尚未新增任何進度。 search_radius: name: 搜尋半徑 - description: "允許你變更玩家周圍\n偵測方塊和/或實體的\n半徑。" - value: 目前距離:[number] + description: |- + 允許你修改 + 以玩家為中心偵測 + 方塊及/或實體的半徑。 + value: '目前距離:[number]' remove_items: name: 移除物品 - description: "切換所需物品是否將\n在完成挑戰後\n從背包中移除。" + description: |- + 切換完成挑戰後, + 是否從玩家背包中 + 移除所需物品。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 required_items: - name: 所需物品 - description: "允許你變更此挑戰\n完成所需的物品。" - title: 物品: + name: 需求物品 + description: |- + 允許你修改 + 完成此挑戰 + 所需的物品。 + title: '物品:' list: ' - [number] x [item]' - none: 未新增任何物品。 + none: 尚未新增任何物品。 add_ignored_meta: name: 新增忽略中繼資料 - description: "允許你指定哪些物品\n應該忽略分配給它們的\n任何中繼資料。" - title: 物品: + description: |- + 允許你指定哪些物品 + 應忽略其 + 中繼資料。 + title: '物品:' list: ' - [number] x [item]' - none: 未新增任何物品。 + none: 尚未新增任何物品。 remove_ignored_meta: name: 移除忽略中繼資料 - description: "移除忽略分配給它們的\n中繼資料的物品。" + description: |- + 移除會忽略 + 中繼資料的物品。 remove_experience: - name: 移除經驗 - description: "切換所需的\n經驗是否將在完成\n挑戰後從玩家移除。" + name: 移除經驗值 + description: |- + 切換完成挑戰後, + 是否扣除玩家 + 所需的經驗值。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 required_experience: - name: 所需經驗 - description: "允許你變更玩家\n所需的經驗。" - value: 目前經驗:[number] + name: 需求經驗值 + description: |- + 允許你修改 + 玩家所需的 + 經驗值。 + value: '目前經驗值:[number]' required_level: - name: 所需島嶼等級 - description: "允許你變更\n挑戰的\n所需島嶼等級。" - value: 目前等級:[number] + name: 需求島嶼等級 + description: |- + 允許你修改 + 完成此挑戰 + 所需的島嶼等級。 + value: '目前等級:[number]' required_materialtags: - name: 所需方塊群組 - description: "允許你變更此挑戰\n所需的方塊群組以\n完成。" - title: 方塊群組: + name: 需求方塊群組 + description: |- + 允許你修改 + 完成此挑戰 + 所需的方塊群組。 + title: '方塊群組:' list: ' - [number] x [tag]' - none: 未新增任何方塊群組。 + none: 尚未新增任何方塊群組。 required_entitytags: - name: 所需實體群組 - description: "允許你變更此挑戰\n所需的實體群組以\n完成。" - title: 實體群組: + name: 需求實體群組 + description: |- + 允許你修改 + 完成此挑戰 + 所需的實體群組。 + title: '實體群組:' list: ' - [number] x [tag]' - none: 未新增任何實體群組。 + none: 尚未新增任何實體群組。 remove_money: - name: 移除金錢 - description: "切換所需的\n金錢是否將從\n玩家帳戶中移除完成\n挑戰後。" + name: 扣除金錢 + description: |- + 切換完成挑戰後, + 是否從玩家帳戶 + 扣除所需金額。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 required_money: - name: 所需金錢 - description: "允許你變更玩家帳戶中\n所需的金錢\n以完成挑戰。" - value: 目前值:[number] + name: 需求金額 + description: |- + 允許你修改 + 完成挑戰所需的 + 玩家帳戶金額。 + value: '目前數值:[number]' required_papi: - name: 所需 PAPI - description: "檢查可以\n包括 PAPI 佔位符\n和數學和邏輯元素的公式。" - value: 公式:[formula] + name: 需求 PAPI + description: |- + 檢查一個可包含 + PAPI Placeholder + 以及數學、邏輯運算的公式。 + value: '公式:[formula]' statistic: name: 統計資料 - description: "允許你變更統計資料\n類型以檢查\n此挑戰。" - value: 目前值:[statistic] + description: |- + 允許你修改 + 此挑戰所檢查的 + 統計資料類型。 + value: '目前數值:[statistic]' statistic_amount: - name: 目標值 - description: "允許你變更目標\n統計資料值\n必須滿足。" - value: 目前值:[number] + name: 目標數值 + description: |- + 允許你修改 + 必須達成的 + 統計資料目標值。 + value: '目前數值:[number]' add_statistic: name: 新增統計資料 - description: "允許你新增\n新統計資料至清單。" + description: |- + 允許你新增 + 統計資料至清單。 remove_statistic: name: 移除統計資料 - description: "允許你移除\n選定的統計資料\n清單。" + description: |- + 允許你移除 + 清單中的 + 統計資料。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 advancement: name: [name] description: '[description]' add_advancement: name: 新增進度 - description: "允許你新增\n新進度至清單。" + description: |- + 允許你新增 + 進度至清單。 remove_advancement: name: 移除進度 - description: "允許你移除\n選定的進度\n清單。" + description: |- + 允許你移除 + 清單中的 + 進度。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 statistic_blocks: name: 目標方塊 - description: "允許你變更統計資料的\n目標方塊。" - value: 目前方塊:[block] + description: |- + 允許你修改 + 統計資料的 + 目標方塊。 + value: '目前方塊:[block]' statistic_items: name: 目標物品 - description: "允許你變更統計資料的\n目標物品。" - value: 目前物品:[item] + description: |- + 允許你修改 + 統計資料的 + 目標物品。 + value: '目前物品:[item]' statistic_entities: name: 目標實體 - description: "允許你變更統計資料的\n目標實體。" - value: 目前實體:[entity] + description: |- + 允許你修改 + 統計資料的 + 目標實體。 + value: '目前實體:[entity]' reward_text: name: 獎勵文字 - description: "指定獎勵文字。\n必須套用顏色代碼。" - value: 目前文字: + description: |- + 設定獎勵文字。 + 需自行加入色彩代碼。 + value: '目前文字:' repeat_reward_text: name: 重複獎勵文字 - description: "指定重複獎勵\n挑戰的文字。\n必須套用顏色代碼。" - value: 目前文字: + description: |- + 設定此挑戰的 + 重複獎勵文字。 + 需自行加入色彩代碼。 + value: '目前文字:' reward_items: name: 獎勵物品 - description: 允許你變更獎勵物品。 - title: 物品: + description: 允許你修改獎勵物品。 + title: '物品:' list: ' - [number] x [item]' - none: 未新增任何物品。 + none: 尚未新增任何物品。 repeat_reward_items: name: 重複獎勵物品 - description: "允許你變更此挑戰的\n重複獎勵物品。" - title: 物品: + description: |- + 允許你修改 + 此挑戰的重複獎勵物品。 + title: '物品:' list: ' - [number] x [item]' - none: 未新增任何物品。 + none: 尚未新增任何物品。 reward_experience: - name: 獎勵經驗 - description: "允許你變更獎勵\n& 玩家的經驗。" - value: 獎勵經驗:[number] + name: 獎勵經驗值 + description: |- + 允許你修改 + 玩家獲得的獎勵經驗值。 + value: '獎勵經驗值:[number]' repeat_reward_experience: - name: 重複獎勵經驗 - description: "允許你變更玩家的\n重複獎勵經驗。" - value: 獎勵經驗:[number] + name: 重複獎勵經驗值 + description: |- + 允許你修改 + 玩家獲得的重複獎勵經驗值。 + value: '獎勵經驗值:[number]' reward_money: - name: 獎勵金錢 - description: 允許你變更獎勵金錢。 - value: 目前值:[number] + name: 獎勵金額 + description: 允許你修改獎勵金額。 + value: '目前數值:[number]' repeat_reward_money: - name: 重複獎勵金錢 - description: "允許你變更挑戰的\n重複獎勵金錢。" - value: 目前值:[number] - reward_chance: - name: 獎勵機率 - description: |- - 完成挑戰時發放物質獎勵的 - 機率百分比(1-100)。 - 物品、金錢和經驗共用一次判定。 - 指令一定會執行。 - value: 機率:[number]% + name: 重複獎勵金額 + description: |- + 允許你修改 + 此挑戰的重複獎勵金額。 + value: '目前數值:[number]' reward_commands: name: 獎勵指令 - description: "指定獎勵指令。\n提示:\n指令不需要前導 `/` 因為它會\n自動套用。\n預設情況下,指令由伺服器執行。\n但是,在開頭新增 `[SELF]` 將導致\n由玩家執行指令。\n它還支援佔位符 `[player]` 將被\n取代為完成挑戰的玩家名稱。" - value: 目前指令: + description: |- + 設定獎勵指令。 + 提示: + 指令前不需要加上「/」, + 系統會自動補上。 + 預設會由伺服器執行指令。 + 若在開頭加入 [SELF], + 則改由玩家自行執行。 + 也支援 [player] Placeholder, + 會自動替換為完成挑戰的玩家名稱。 + value: '目前指令:' repeat_reward_commands: name: 重複獎勵指令 - description: "指定挑戰的重複獎勵指令。\n提示:\n指令不需要前導 `/` 因為它會\n自動套用。\n預設情況下,指令由伺服器執行。\n但是,在開頭新增 `[SELF]` 將導致\n由玩家執行指令。\n它還支援佔位符 `[player]` 將被\n取代為完成挑戰的玩家名稱。" - value: 目前指令: + description: |- + 設定此挑戰的重複獎勵指令。 + 提示: + 指令前不需要加上「/」, + 系統會自動補上。 + 預設會由伺服器執行指令。 + 若在開頭加入 [SELF], + 則改由玩家自行執行。 + 也支援 [player] Placeholder, + 會自動替換為完成挑戰的玩家名稱。 + value: '目前指令:' repeatable: - name: 可重複的 - description: 切換挑戰是否可重複。 + name: 可重複完成 + description: 切換此挑戰是否可重複完成。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 repeat_count: - name: 重複計數 + name: 重複次數 description: |- - 允許你變更挑戰的 - 重複次數。 - 設為 0 表示無限次重複。 - value: 目前值:[number] - value-infinite: "目前值:[number] (無限)" + 允許你修改 + 此挑戰可重複完成的次數。 + value: '目前數值:[number]' cool_down: - name: 冷卻 - description: "允許你變更冷卻\n期間(以秒為單位)必須經過\n可重複挑戰完成之間。" - value: 目前值:[time] + name: 冷卻時間 + description: |- + 允許你修改 + 可重複完成挑戰之間 + 所需等待的時間(秒)。 + value: '目前數值:[time]' challenges: name: 挑戰 - description: "查看指派的挑戰\n至等級。" + description: |- + 檢視指派至 + 此等級的挑戰。 waiver_amount: - name: 豁免數量 - description: "允許你設定挑戰數量\n可以保持未完成以解鎖\n下一個等級。" - value: 目前值:[number] + name: 可略過數量 + description: |- + 允許你設定可未完成 + 多少項挑戰即可解鎖 + 下一個等級。 + value: '目前數值:[number]' add_challenges: - name: 新增挑戰(-s) - description: "允許你選擇並新增\n挑戰至等級。" + name: 新增挑戰 + description: |- + 允許你選擇並新增 + 挑戰至此等級。 remove_challenges: - name: 移除挑戰(-s) - description: "允許你選擇並移除\n等級的挑戰。" + name: 移除挑戰 + description: |- + 允許你選擇並移除 + 此等級中的挑戰。 reset_on_new: - name: 新增時重設 - description: "切換當使用者離開\n& 時是否應該重設挑戰\n他們的島嶼或建立新島嶼。" + name: 建立新島時重設 + description: |- + 切換玩家離開島嶼 + 或建立新島時, + 是否重設挑戰。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 broadcast: name: 廣播 - description: "首次完成廣播\n挑戰或等級給所有人。" + description: |- + 首次完成挑戰或等級時, + 向所有玩家廣播。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 remove_completed: - name: 隱藏已完成 - description: "隱藏已完成的挑戰\n從選單。" + name: 隱藏已完成項目 + description: |- + 將已完成的挑戰 + 從選單中隱藏。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 glow_completed: - name: 已完成的挑戰發光 - description: "套用附魔發光\n至已完成的挑戰。" + name: 已完成挑戰發光 + description: |- + 為已完成的挑戰 + 套用附魔發光效果。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 glow_completed_levels: - name: 已完成的等級發光 - description: "套用附魔發光\n至已完成的等級。" + name: 已完成等級發光 + description: |- + 為已完成的等級 + 套用附魔發光效果。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 store_history: - name: 儲存歷史記錄 - description: "每次完成時儲存內部歷史記錄\n挑戰。\n目前僅在資料庫中可查看。" + name: 儲存歷史紀錄 + description: |- + 每次完成挑戰時 + 儲存內部歷史紀錄。 + 目前僅能於 + 資料庫中檢視。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 data_per_island: - name: 每島儲存 - description: "在每島基礎上儲存\n已完成的挑戰。\n進度將被分享\n與所有團隊成員。" + name: 依島嶼儲存 + description: |- + 依照島嶼儲存 + 已完成的挑戰。 + 進度會與所有 + 隊伍成員共享。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 show_title: name: 顯示標題 - description: "在完成挑戰時顯示標題\n或等級。" + description: |- + 完成挑戰或等級時 + 顯示標題。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 gamemode_gui: - name: GameMode 選擇 GUI - description: "啟用可透過存取的單一 GUI\n/challenges 指令。\n(需要伺服器重新啟動。)" + name: 遊戲模式選擇選單 + description: |- + 啟用可透過 + /challenges 指令開啟的 + 單一選單。 + (需重新啟動伺服器) enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 locked_level_icon: name: 預設鎖定等級圖示 - description: "所有鎖定等級的預設圖示。\n每個等級都可以覆蓋此圖示。" + description: |- + 所有鎖定等級的預設圖示。 + 每個等級皆可個別覆寫。 purge_history: - name: 歷史記錄生命週期 - description: "指定天數\n歷史記錄資料被儲存在\n使用者資料。\n值 0 表示資料將\n不會被移除。" - value: 目前值:[number] + name: 歷史紀錄保存天數 + description: |- + 設定玩家資料中 + 歷史紀錄的保存天數。 + 設為 0 表示 + 永不刪除。 + value: '目前數值:[number]' title_showtime: name: 標題顯示時間 - description: "標題將被顯示的 tick 數\n& 至玩家。" - value: 目前值:[number] + description: |- + 設定標題 + 顯示給玩家的 + Tick 數。 + value: '目前數值:[number]' active_world_list: - name: 僅顯示作用中的世界 - description: "若 GameMode 選擇 GUI\n啟用,此設定決定\nGUI 是否顯示\nGameMode 選擇或挑戰\n當前世界。\n(需要伺服器重新啟動。)" + name: 僅顯示目前世界 + description: |- + 若已啟用遊戲模式選擇選單, + 此設定決定選單 + 要顯示遊戲模式選擇, + 還是目前世界的挑戰。 + (需重新啟動伺服器) enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 visibility_mode: - name: 可見度模式 - description: 隱藏的挑戰的可見度模式。 + name: 顯示模式 + description: 設定隱藏挑戰的顯示方式。 enabled: disabled: - visible: 顯示可見的挑戰 + visible: 僅顯示可見挑戰 hidden: 顯示所有挑戰 toggleable: 允許切換 include_undeployed: - name: 包括未部署的挑戰 - description: "指示未部署的挑戰\n應計入等級完成。" + name: 包含未部署挑戰 + description: |- + 設定未部署的挑戰 + 是否納入等級完成度計算。 enabled: 已啟用 - disabled: 已禁用 + disabled: 已停用 download: name: 下載圖書館 - description: "手動更新可用的\n挑戰圖書館。" + description: |- + 手動更新可用的 + 挑戰圖書館。 enabled: 清除快取 - disabled: 不清除快取 + disabled: 保留快取 language: name: 語言 - description: "依語言篩選\n挑戰圖書館。" - current: 顯示:[lang] + description: |- + 依語言篩選 + 挑戰圖書館。 + current: '目前顯示:[lang]' all: 全部 player: name: [name] - description: 島主:[owner] - members: 島嶼成員: + description: '島主:[owner]' + members: '島嶼成員:' member: - [name] - no-island: "此玩家沒有\n島嶼。" + no-island: |- + 此玩家 + 沒有島嶼。 player_list: - name: 選擇使用者清單 - description: "選擇應該顯示\n的使用者清單。" + name: 選擇玩家清單 + description: |- + 選擇要顯示的 + 玩家清單。 enabled: disabled: online: 在線玩家 - with_island: 有島嶼的玩家 - in_world: 在世界中的玩家 + with_island: 擁有島嶼的玩家 + in_world: 世界中的玩家 add_block: name: 新增方塊 - description: "允許你新增\n新方塊至清單。" + description: |- + 允許你新增 + 方塊至清單。 add_block_group: name: 新增方塊群組 - description: "允許你新增\n新方塊群組至清單。" + description: |- + 允許你新增 + 方塊群組至清單。 remove_block: name: 移除方塊 - description: "允許你移除\n選定的方塊\n清單。" - title: 選定的材料: + description: |- + 允許你移除 + 清單中的 + 方塊。 + title: '已選取的方塊:' material: - [material] remove_block_group: name: 移除方塊群組 - description: "允許你移除\n選定的方塊群組\n清單。" - title: 選定的方塊群組: + description: |- + 允許你移除 + 清單中的 + 方塊群組。 + title: '已選取的方塊群組:' material: - [material] material: name: [material] - description: 材料 ID:[id] - selected: 已選擇 + description: '材料 ID:[id]' + selected: 已選取 block-group: name: [id] description: '' - selected: 已選擇 + selected: 已選取 add_entity: name: 新增實體 - description: "允許你新增\n新實體至清單。" + description: |- + 允許你新增 + 實體至清單。 add_entity_group: name: 新增實體群組 - description: "允許你新增\n新實體群組至清單。" + description: |- + 允許你新增 + 實體群組至清單。 switch_entity: - name: 切換蛋 - description: "允許你從\n蛋切換至暴徒頭。" + name: 切換顯示方式 + description: |- + 在生怪蛋 + 與生物頭顱之間切換。 remove_entity: name: 移除實體 - description: "允許你移除\n選定的實體\n清單。" - title: 選定的實體: + description: |- + 允許你移除 + 清單中的 + 實體。 + title: '已選取的實體:' entity: - [entity] remove_entity_group: name: 移除實體群組 - description: "允許你移除\n選定的實體群組\n清單。" - title: 選定的實體群組: + description: |- + 允許你移除 + 清單中的 + 實體群組。 + title: '已選取的實體群組:' entity: - [tag] entity: name: [entity] - description: 實體 ID:[id] - selected: 已選擇 + description: '實體 ID:[id]' + selected: 已選取 entity-group: name: [id] description: '' - selected: 已選擇 + selected: 已選取 inventory_type: name: 背包類型 - description: "檢查物品的挑戰\n在玩家的背包。" + description: |- + 檢查玩家背包內 + 物品的挑戰。 island_type: name: 島嶼類型 - description: "檢查方塊的挑戰\n或玩家周圍的實體。" + description: |- + 檢查玩家周圍 + 方塊或實體的挑戰。 other_type: name: 其他類型 - description: "利用外掛程式的挑戰\n或附加元件功能,\n如等級和金錢。" + description: |- + 使用外掛或 + 附加元件功能的挑戰, + 例如島嶼等級或金錢。 statistic_type: name: 統計資料類型 - description: "檢查\n玩家統計資料。" + description: |- + 檢查玩家 + 統計資料的挑戰。 save: name: 儲存 - description: "儲存變更及\n返回。" + description: |- + 儲存變更 + 並返回。 cancel: name: 取消 - description: "捨棄變更及\n返回。" + description: |- + 捨棄變更 + 並返回。 accept_selected: - name: 接受選定 - description: "返回選定的元素\n並重新開啟前一個 GUI。" - title: 已選擇: + name: 確認選取 + description: |- + 確認所選項目, + 並重新開啟上一個選單。 + title: '已選取:' element: - [element] advancement_element: name: [name] description: '[description]' - selected: 已選擇 + selected: 已選取 statistic_element: name: [statistic] - amount: 目標值:[number] + amount: '目標數值:[number]' remove: - name: 減少統計資料:[value] + name: '扣除統計資料:[value]' value: enabled: 已啟用 - disabled: 已禁用 - block: 目標方塊:[block] - item: 目標物品:[item] - entity: 目標實體:[entity] + disabled: 已停用 + block: '目標方塊:[block]' + item: '目標物品:[item]' + entity: '目標實體:[entity]' description: '[description]' - selected: 已選擇 + selected: 已選取 environment_element: name: [environment] description: '[description]' search: name: 搜尋 - description: "允許你搜尋\n使用文字輸入值的元素。" - search: 值:[value] - toggle-undeployed: - name: "未部署的挑戰" - shown: |- - 未部署的挑戰目前 - 顯示。 - hidden: |- - 未部署的挑戰目前 - 隱藏。 - required_biomes: - name: "所需生態域" - description: |- - 玩家必須站在這些生態域 - 之一中才能完成此 - 島嶼挑戰。 - title: "生態域:" - list: " - [biome]" - none: "無需特定生態域(任何生態域)。" - reward_island_level: - name: "獎勵島嶼等級" - description: |- - 允許你變更獎勵的島嶼等級。 - 需要 Level 插件。 - value: "目前值:[number]" - repeat_reward_island_level: - name: "重複獎勵島嶼等級" - description: |- - 允許你變更挑戰重複完成時 - 獎勵的島嶼等級。 - 需要 Level 插件。 - value: "目前值:[number]" - open_anywhere: - name: "隨處開啟 GUI" - description: |- - 允許玩家在任何地方開啟挑戰 GUI。 - 受保護時,完成挑戰仍需 - 身處島嶼上。 - enabled: "已啟用" - disabled: "已禁用" - biome: - name: "[biome]" - description: "生態域 ID:[id]" - selected: "已選擇" + description: |- + 允許你輸入文字 + 搜尋指定項目。 + search: '搜尋值:[value]' + tips: + click-to-select: 點擊 即可選取。 + click-to-choose: 點擊 即可選擇。 + click-to-complete: 點擊 即可完成。 + right-click-multiple-open: 右鍵 即可選擇完成次數。 + shift-left-click-to-complete-all: Shift + 左鍵 即可全部完成。 + left-click-to-accept: 左鍵 即可完成。 + right-click-to-write: 右鍵 即可輸入。 + click-to-reduce: 點擊 即可減少。 + click-to-increase: 點擊 即可增加。 + click-to-return: 點擊 即可返回。 + click-to-quit: 點擊 即可離開。 + click-to-wipe: 點擊 即可清除。 + left-click-to-wipe: 左鍵 即可清除。 + right-click-to-switch: 右鍵 即可切換。 + click-to-open: 點擊 即可開啟。 + click-to-export: 點擊 即可匯出。 + click-to-create: 點擊 即可建立。 + left-click-to-open: 左鍵 即可開啟。 + right-click-to-reset-all: 右鍵 即可全部重設。 + click-to-toggle: 點擊 即可切換。 + click-to-change: 點擊 即可變更。 + shift-click-to-reset: Shift + 點擊 即可重設。 + click-to-add: 點擊 即可新增。 + click-to-remove: 點擊 即可移除。 + left-click-to-cycle: 左鍵 即可切換至上一個選項。 + right-click-to-cycle: 右鍵 即可切換至下一個選項。 + click-to-edit: 點擊 即可編輯。 + left-click-to-download: 左鍵 即可下載。 + right-click-to-toggle: 右鍵 即可切換。 + click-to-install: 點擊 即可安裝。 + click-to-reset-all: 點擊 即可全部重設。 + right-click-to-select: 右鍵 即可選取。 + right-click-to-deselect: 右鍵 即可取消選取。 + right-click-to-reset: 右鍵 即可重設。 + left-click-to-choose: 左鍵 即可選擇。 + click-to-cancel: 點擊 即可取消。 + click-to-save: 點擊 即可儲存。 + click-to-deselect: 點擊 即可取消選取。 + click-on-item: |- + 請點擊 背包中的 + 物品。 + left-click-to-edit: 左鍵 即可編輯。 + right-click-to-clear: 右鍵 即可清除。 + click-to-previous: 點擊 即可查看上一頁。 + click-to-next: 點擊 即可查看下一頁。 descriptions: - admin: - save: '保存幷返回上一級菜單' - cancel: '取消任何操作幷返回上一級菜單' - input: '打開文本字段輸入' - set: '設置操作,擊數字會將值更改爲所選數字。' - increase: '增加操作。 單擊數字將增加所選數字的值。' - reduce: '减少操作。 單擊數字將减少所選數字的值。' - multiply: '乘法運算。 單擊數字會將值乘以所選數字。' - import: '導入ASkyblock挑戰。|右鍵單擊它啓用/禁用覆蓋模式。|將Challenges.yml放在./BentoBox/addons/Challenges文件夾中。' - complete: '爲某個玩家完成某個挑戰|玩家無法獲得完成獎勵。' - reset: '重置已完成的玩家挑戰。|右鍵單擊啓用/禁用重置所有功能。' - create-challenge: '添加新挑戰。|默認情况下,它將在免費挑戰列表中。' - create-level: '添加新的挑戰等級。' - edit-challenge: '編輯某個挑戰設定' - edit-level: '編輯某個挑戰等級設定' - delete-challenge: '删除某個挑戰' - delete-level: '删除某個挑戰等級' - settings: '修改組件設定' - properties: '修改常規屬性' - requirements: '修改挑戰需求' - rewards: '修改挑戰獎勵' - challenges: '管理挑戰級別 (添加/删除).' - deployment: '查看某玩家已完成的挑戰' - icon-challenge: '將在此挑戰的GUI面板中顯示的圖標。' - icon-level: '將在此級別的GUI面板中顯示的圖標。' - locked-icon: '如果級別被鎖定,將在GUI面板中顯示的圖標。' - description: '編輯介紹' - order: '更改挑戰順序' - environment: '改變挑戰運作的環境。' - type: '更改挑戰類型(不同類型的挑戰偵測方式不同)' - remove-on-complete: '在玩家完成挑戰後是否删除該挑戰圖標于任務面板中' - name-challenge: '修改挑戰名稱' - name-level: '修改挑戰等級名稱' - required-entities: '修改挑戰需要的實體.|實體:|' - remove-entities: '是否在挑戰結束後删除挑戰需要的實體' - required-blocks: '修改挑戰需要的方塊.|方塊:|' - remove-blocks: '是否在挑戰結束後删除任務需求方塊(替換爲空氣)' - search-radius: '玩家完成挑戰時檢測實體/方塊的範圍(半徑)' - required-permissions: '玩家需要具有以下權限才能完成挑戰|權限:' - required-items: '玩家背包中需要有以下物品才能完成挑戰|物品:' - remove-items: '是否在完成挑戰後删除玩家背包中的挑戰需求物品' - required-experience: '玩家需要有該項目所設置的經驗值才可以完成挑戰' - remove-experience: '是否在玩家完成挑戰後删除任務需求的經驗值' - required-level: '玩家需要島嶼等級達到該項目所設置的等級才能完成挑戰.|需要 Level 組件.' - required-money: '玩家需要有該項目所設置的金錢才能完成挑戰.|需要經濟前置.' - remove-money: '是否在玩家完成挑戰後删除任務需求的金錢.|需要經濟前置.' - reward-text: '設置完成任務後的獎勵信息' - reward-items: '設置完成任務後的物品獎勵.|物品:' - reward-experience: '設置完成任務後的經驗獎勵.' - reward-money: '設置完成任務後的金錢獎勵.|需要經濟前置.' - reward-commands: '設置完成任務後的指令獎勵.|指令:' - repeatable: '挑戰是否可以重複' - repeat-count: '重複挑戰的次數,如果設置爲0則爲無限制' - repeat-reward-text: '重複挑戰完成後的信息' - repeat-reward-items: '重複挑戰完成後的物品獎勵.|物品:' - repeat-reward-experience: '重複挑戰完成後的經驗獎勵.' - repeat-reward-money: '重複挑戰完成後的金錢獎勵.|需要經濟前置.' - repeat-reward-commands: '重複挑戰完成後的指令獎勵.||指令:' - waiver-amount: '完成該數量的挑戰玩家方能解鎖下一挑戰級別的挑戰' - reward-text-level: '完成某挑戰級別所有挑戰後發送給玩家的信息' - add-challenge: '將現有挑戰添加到當前挑戰級別' - remove-challenge: '從當前級別删除挑戰' - reset-on-new: '允許/禁止,當玩家重置/踢出島嶼後都會重置挑戰' - broadcast: '允許/禁止,當玩家完成第一次挑戰後向全服玩家廣播' - remove-completed: '允許/禁止,在玩家挑戰列表中隱藏已完成的挑戰' - glow: '允許/禁用,在已完成的挑戰中加上附魔效果' - free-at-top: '改變免費挑戰的位置,如果爲true免費挑戰會放在前排,如果爲false免費挑戰將放在後排' - line-length: '修改每條lore的最大長度' - toggle-user-list: '切換到不同的玩家列表' - mode-online: '目前在綫的玩家' - mode-in-world: 'Players which is in GameMode world.' - mode-with-island: 'Players which has island in GameMode.' - selected: '已選中' - remove-selected: '删除所選目標|您可以使用鼠標右鍵選擇目標' - show-eggs: '在Egg模式或Head模式之間切換實體視圖' - level-lore: '修改挑戰級別介紹的哪些目標是可見的' - challenge-lore: '修改挑戰介紹的哪些目標是可見的' - gui-view-mode: '如果玩家輸入/challenges,菜單應該顯示GameModes還是挑戰' - history-store: '允許啓用/禁用質詢歷史存儲' - history-lifespan: '允許修改將保存歷史數據的天數| 0表示永久' - island-store: '啓用/禁用挑戰每個島的數據存儲。如果啓用此選項,整個島嶼團隊的挑戰進度將是相同的。|不會在點擊時轉換數據。進展將會失敗。' - default-locked-icon: '更改默認鎖定級別圖標。|此級別可以覆蓋此選項。' - gui-mode: '啓用/禁用單一挑戰GUI。|要求服務器重啓。' - click-to-edit: '點擊此處編輯輸入.' - edit-text-line: '編輯文本!' - add-text-line: '添加新的文本!' - input-mode: '在聊天和鐵砧輸入模式之間切換。' - title-enable: '啓用/禁用玩家完成挑戰時顯示的標題消息。' - title-showtime: '修改標題消息對玩家可見的時間。' - default-import: '導入插件自帶挑戰' - default-export: '將現有的挑戰導出至 defaults.json 文件中.' - complete-wipe: '清空插件數據庫中的所有挑戰,包括玩家的挑戰數據!' - current-value: '|當前值: [value].' - enabled: '有效' - disabled: '禁用' - type: - island: '- 島嶼類型:| (主要通過檢測玩家身邊的方塊和生物)' - inventory: '- 庫存類型:| (主要通過檢測玩家的背包物品)' - other: '- 其他類型:| (主要通過檢測服務器的其他插件/組件)' - the-end: '- 末地' - nether: '- 地獄' - normal: '- 主世界' - entity: '- [entity] : [count]' - block: '- [block] : [count]' - permission: '- [permission]' - item: '- [count] x [item]' - item-meta: ' ([meta])' - item-enchant: ' - [enchant] [level]' - command: '- [command]' - level-unlocked: '點擊查看 [level] 級別的挑戰!' - level-locked: '請完成 [count] 個 [level] 級別的挑戰來解鎖這個挑戰級別!' + # This part generates description text for challenges object in all GUI's. challenge: - lore: "[description]\n[status]\n[cooldown]\n[requirements]\n[rewards]" - team-requirement: 團隊:[online] 在線([number] 必需) - team-required: 需要團隊才能完成 + # The main part that generates description text. + # [description] comes from challenge.description + lore: |- + [description] + [status] + [cooldown] + [requirements] + [rewards] +# Team challenge lore line. [online] members online, [number] required, [size] team size. + team-requirement: '隊伍:[online] 人在線(需 [number] 人)' + # Shown instead of the above when the viewer has no team. + team-required: 需要加入隊伍才能完成 + # Contains a text generated inside [status] lore status: completed: 已完成 completed-times: 已完成 [number] 次 - completed-times-of: 已完成 [number] 出自 [max] 次 + completed-times-of: 已完成 [number] / [max] 次 completed-times-reached: 已完成全部 [max] 次 + # Contains a text generated inside [cooldown] lore cooldown: - lore: "[timeout]\n[wait-time]" - timeout: 冷卻:[time] - wait-time: 可用於:[time] + lore: |- + [timeout] + [wait-time] + timeout: '冷卻時間:[time]' + wait-time: '可再次完成時間:[time]' in-days: '[number] 天 ' in-hours: '[number] 小時 ' - in-minutes: '[number] 分鐘 ' + in-minutes: '[number] 分 ' in-seconds: '[number] 秒' + # Contains a text generated inside [requirements] lore requirements: - lore: "[environment]\n[type-requirement]\n[permissions]" - environment-single: 限制於 [environment] - environment-title: 限制於: + lore: |- + [environment] + [type-requirement] + [permissions] + environment-single: 限定於 [environment] + environment-title: '限定維度:' environment-list: ' - [environment]' - permission-single: 需要 [permission] 權限。 - permissions-title: 需要權限: + permission-single: 需要權限:[permission] + permissions-title: '需要以下權限:' permissions-list: ' - [permission]' island: - lore: "[blocks]\n[entities]\n[search-radius]\n[warning-block]\n[warning-entity]" - blocks-title: 所需方塊: + lore: |- + [blocks] + [entities] + [search-radius] + [warning-block] + [warning-entity] + blocks-title: '需求方塊:' block-value: ' - [material]' blocks-value: ' - [number] x [material]' - entities-title: 所需實體: + entities-title: '需求實體:' entity-value: ' - [entity]' entities-value: ' - [number] x [entity]' - search-radius: 不超過 [number] 米 - warning-block: 方塊將被 移除 - warning-entity: 實體將被 移除 - biomes-title: "所需生態域:" - biome-value: " - [biome]" + search-radius: 距離玩家不得超過 [number] 格 + warning-block: 完成後將移除方塊 + warning-entity: 完成後將移除實體 inventory: - lore: "[items]\n[warning]" - item-title: 所需物品: + lore: |- + [items] + [warning] + item-title: '需求物品:' item-value: ' - [item]' items-value: ' - [number] x [item]' - warning: 物品將被 移除 + warning: 完成後將移除物品 other: - lore: "[experience]\n[experience-warning]\n[money]\n[money-warning]\n[level]" - experience: 所需經驗:[number] - experience-warning: 經驗將被 移除 - money: 所需金錢:[number] - money-warning: 金錢將被 移除 - level: 所需島嶼等級:[number] + lore: |- + [experience] + [experience-warning] + [money] + [money-warning] + [level] + experience: '需求經驗值:[number]' + experience-warning: 完成後將扣除經驗值 + money: '需求金額:[number]' + money-warning: 完成後將扣除金額 + level: '需求島嶼等級:[number]' statistic: - lore: "[statistic]\n[warning]" - multiple-target: [statistic]:[number] x [target] - single-target: [statistic]:[target] - statistic: [statistic] [number] - warning: 統計資料將被 減少 + lore: |- + [statistic] + [warning] + multiple-target: '[statistic]:[number] x [target]' + single-target: '[statistic]:[target]' + statistic: '[statistic]:[number]' + warning: 完成後將扣除統計資料 + # Contains a text generated inside [rewards] lore rewards: - lore: "獎勵:\n[text]\n[items]\n[experience]\n[money]\n[commands]" - item-title: 物品: + lore: |- + 獎勵: + [text] + [items] + [experience] + [money] + [commands] + item-title: '物品:' item-value: ' - [item]' items-value: ' - [number] x [item]' - experience: 經驗:[number] - money: 金錢:[number] - commands-title: 指令: + experience: '經驗值:[number]' + money: '金額:[number]' + commands-title: '指令:' command: ' - [command]' + + # This part generates description text for levels object in all GUI's. level: - lore: "[text]\n[status]\n[waiver]\n[rewards]" + lore: |- + [text] + [status] + [waiver] + [rewards] status: completed: 已完成 - completed-challenges-of: 已完成 [number] 出自 [max] 挑戰。 + completed-challenges-of: 已完成 [number] / [max] 項挑戰 locked: 已鎖定 - missing-challenges: "需要完成 [number] 更多挑戰\n以解鎖此等級。" - waiver: "[number] 挑戰可以\n跳過以解鎖下一個等級。" + missing-challenges: |- + 還需要完成 + [number] 項挑戰 + 才能解鎖此等級。 + waiver: |- + 可略過 [number] 項挑戰, + 即可解鎖下一個等級。 rewards: - lore: "獎勵:\n[text]\n[items]\n[experience]\n[money]\n[commands]" - item-title: 物品: + lore: |- + 獎勵: + [text] + [items] + [experience] + [money] + [commands] + item-title: '物品:' item-value: ' - [item]' items-value: ' - [number] x [item]' - experience: 經驗:[number] - money: 金錢:[number] - commands-title: 指令: + experience: '經驗值:[number]' + money: '金額:[number]' + commands-title: '指令:' command: ' - [command]' - library: - author: 由 [author] - version: 使用挑戰 [version] 製作 - lang: 語言:[lang] - gamemode: 主要用於 [gamemode] - challenge-description: - level: '挑戰級別: [level]' - completed: '已完成' - completed-times-of: '完成次數: [donetimes] 上限: [maxtimes]' - maxed-reached: '完成次數: [donetimes] 上限: [maxtimes]' - completed-times: '已完成 [donetimes]' - warning-items-take: '完成此挑戰後,該挑戰的需要物品將會被清空' - objects-close-by: '任務需求的方塊/生物不能離你太遠!(超出偵測範圍)' - warning-entities-kill: '完成此挑戰後,該挑戰需要的生物將會被清空' - warning-blocks-remove: '完成此挑戰後,該挑戰需要的方塊將會被清空' - not-repeatable: '該挑戰不可重複!' - experience-reward: '經驗獎勵: [value]' - money-reward: '金錢獎勵: $[value]' - required-experience: '所需經驗: [value]' - required-money: '所需金錢: $[value]' - required-island-level: '所需島嶼等級: [value]' - environment: '所需實體:' - reward-items: '物品獎勵:' - reward-commands: '指令獎勵:' - required-items: '所需物品:' - required-entities: '所需實體:' - required-blocks: '所需方塊:' - level-description: - completed: '已完成' - completed-challenges-of: '&你已經完成 [number] 個該級別的挑戰,達到了 [max]個挑戰.' - waver-amount: '可以跳過[value] 個挑戰來解鎖下一個挑戰級別.' - experience-reward: '經驗獎勵: [value]' - money-reward: '金錢獎勵: $[value]' - reward-items: '物品獎勵:' - reward-commands: '指令獎勵:' - item-description: - item: '- [count] x [item]' - item-meta: ' ([meta])' - item-enchant: ' - [enchant] [level]' - item-name: ' [name]' - item-lore: ' 物品Lore:' - book-meta: ' [title] by [author]' - recipe-count: ' [count] recipes' - armor-color: ' [color]' - potion-type-extended-upgraded: ' [name]' - potion-type-upgraded: ' Upgraded [name]' - potion-type-extended: ' Extended [name]' - potion-type: ' [name]' - custom-effects: ' 自定義效果:' - potion-effect: ' [effect] x [amplifier] for [duration]t' - skull-owner: ' [owner]' - egg-meta: ' [mob]' - fish-meta: ' [body-color] with [pattern-color] [pattern]' - questions: - prefix: "[SERVER]: " - - admin: - number: "Write a number in chat and press enter to accept it and press enter." - unique-id: "Write object unique name and press enter." - challenge-name: "Write in chat display name for current challenge." - level-name: "Write in chat display name for current level." - titles: - player-gui: 挑戰選單 - gamemode-gui: 選擇遊戲模式 - multiple-gui: 要進行幾次? - admin-gui: 挑戰管理員選單 - edit-challenge: 編輯 [challenge] - edit-level: 編輯 [level] - settings: 設定 - choose-challenge: 選擇挑戰 - choose-level: 選擇等級 - choose-player: 選擇玩家 - library: 圖書館 - manage-blocks: 管理方塊 - manage-block-groups: 管理方塊群組 - manage-entity-groups: 管理實體群組 - manage-entities: 管理實體 - manage-statistics: 管理統計資料 - manage-advancements: 管理進度 - advancement-selector: 進度選擇器 - type-selector: 挑戰類型選擇器 - item-selector: 物品選擇器 - block-selector: 方塊選擇器 - entity-selector: 實體選擇器 - challenge-selector: 挑戰選擇器 - statistic-selector: 統計資料選擇器 - environment-selector: 環境選擇器 - biome-selector: "生態域選擇器" - tips: - click-to-select: 按一下 以選擇。 - click-to-choose: 按一下 以選擇。 - click-to-complete: 按一下 以完成。 - right-click-multiple-open: 按右鍵 選擇完成計數。 - shift-left-click-to-complete-all: 按 Shift+按一下 完成全部。 - left-click-to-accept: 左鍵 完成。 - right-click-to-write: 按右鍵 以寫。 - click-to-reduce: 按一下 以減少。 - click-to-increase: 按一下 以增加。 - click-to-return: 按一下 以返回。 - click-to-quit: 按一下 退出。 - click-to-wipe: 按一下 清除。 - left-click-to-wipe: 左鍵 清除。 - right-click-to-switch: 按右鍵 切換。 - click-to-open: 按一下 開啟。 - click-to-export: 按一下 匯出。 - click-to-create: 按一下 建立。 - left-click-to-open: 左鍵 開啟。 - right-click-to-reset-all: 按右鍵 全部重設。 - click-to-toggle: 按一下 切換。 - click-to-change: 按一下 變更。 - shift-click-to-reset: 按 Shift+按一下 重設。 - click-to-add: 按一下 新增。 - click-to-remove: 按一下 移除。 - left-click-to-cycle: 左鍵 向下循環。 - right-click-to-cycle: 按右鍵 向上循環。 - click-to-edit: 按一下 編輯。 - left-click-to-download: 左鍵 下載。 - right-click-to-toggle: 按右鍵 切換。 - click-to-install: 按一下 安裝。 - click-to-reset-all: 按一下 全部重設。 - right-click-to-select: 按右鍵 選擇。 - right-click-to-deselect: 按右鍵 取消選擇。 - right-click-to-reset: 按右鍵 重設。 - left-click-to-choose: 左鍵 選擇。 - click-to-cancel: 按一下 取消。 - click-to-save: 按一下 儲存。 - click-to-deselect: 按一下 取消選擇。 - click-on-item: 按一下 背包中的物品。 - left-click-to-edit: 左鍵 編輯。 - right-click-to-clear: 按右鍵 清除。 - click-to-previous: 按一下 查看上一頁。 - click-to-next: 按一下 查看下一頁。 + # This part generates description for the Library Entry + library: + author: 作者:[author] + version: 使用 Challenges [version] 製作 + lang: '語言:[lang]' + gamemode: 主要適用於 [gamemode] + conversations: + prefix: '[BentoBox]: ' + confirm-string: true, on, yes, confirm, y, valid, correct + deny-string: false, off, no, deny, n, invalid, incorrect + cancel-string: cancel + exit-string: cancel, exit, quit + cancelled: 對話已取消! + input-number: 請在聊天室輸入一個數字。 + input-seconds: 請在聊天室輸入秒數。 + numeric-only: 輸入的 [value] 不是有效的數字! + not-valid-value: 輸入的數值 [value] 無效!必須大於 [min] 且小於 [max]! + user-data-removed: [gamemode] 的所有玩家資料已從資料庫中清除。 + confirm-user-data-deletion: 請確認是否要清除 [gamemode] 的玩家資料庫。 + challenge-data-removed: [gamemode] 的所有挑戰資料已從資料庫中清除。 + confirm-challenge-data-deletion: 請確認是否要清除 [gamemode] 的挑戰資料庫。 + all-data-removed: [gamemode] 的所有附加元件資料已從資料庫中清除。 + confirm-all-data-deletion: 請確認是否要清除 [gamemode] 的所有附加元件資料。 + write-name: 請在聊天室輸入名稱。 + new-object-created: 已為 [gamemode] 建立新的物件。 + object-already-exists: 物件 [id] 已存在,請選擇其他名稱。 + invalid-challenge: 挑戰 [challenge] 包含無效資料,因此無法部署! + name-changed: '成功:名稱已更新。' + write-description: 請在聊天室輸入新的描述。完成後請在新的一行輸入「quit」。 + description-changed: '成功:描述已更新。' + write-permissions: 請在聊天室逐行輸入所需權限。完成後請在新的一行輸入「quit」。 + permissions-changed: '成功:挑戰權限已更新。' + write-reward-text: 請在聊天室輸入新的獎勵文字。完成後請在新的一行輸入「quit」。 + reward-text-changed: '成功:獎勵文字已更新。' + write-repeat-reward-text: 請在聊天室輸入新的重複獎勵文字。完成後請在新的一行輸入「quit」。 + repeat-reward-text-changed: '成功:重複獎勵文字已更新。' + write-reward-commands: 請在聊天室逐行輸入新的獎勵指令。完成後請在新的一行輸入「quit」。 + reward-commands-changed: '成功:獎勵指令已更新。' + write-repeat-reward-commands: 請在聊天室逐行輸入新的重複獎勵指令。完成後請在新的一行輸入「quit」。 + repeat-reward-commands-changed: '成功:重複獎勵指令已更新。' + challenge-removed: [gamemode] 的挑戰 [challenge] 已從資料庫中移除。 + confirm-challenge-deletion: 請確認是否要從資料庫中移除 [gamemode] 的挑戰 [challenge]。 + level-removed: [gamemode] 的等級 [level] 已從資料庫中移除。 + confirm-level-deletion: 請確認是否要從資料庫中移除 [gamemode] 的等級 [level]。 + start-downloading: 開始下載並匯入挑戰圖書館。 + written-text: '輸入內容:' + confirm-data-replacement: 請確認是否要以新的挑戰取代目前的挑戰資料。 + new-challenges-imported: '成功:[gamemode] 的新挑戰已匯入。' + exported-file-name: 請輸入匯出資料庫檔案的檔名。(輸入「cancel」即可取消) + database-export-completed: '成功:[world] 的資料庫已匯出完成,已產生檔案 [file]。' + file-name-exist: 名為「[id]」的檔案已存在,無法覆寫。 + write-search: 請輸入搜尋內容。(輸入「cancel」即可取消) + search-updated: 搜尋內容已更新。 + enter-formula: |- + 請輸入公式,只能使用 PAPI Placeholder,以及 =、<、>、<=、>=、==、!=、AND、OR 等符號。 + 範例:%my_lifetime_count% >= 1000 AND %island_level% >= 100 titles: -# Title and subtitle my contain variable in [] that will be replaced with proper message from challenge object. -# [friendlyName] will be replaced with challenge friendly name. -# [level] will be replaced with level friendly name. -# [rewardText] will be replaced with challenge reward text. - challenge-title: '完成挑戰' + challenge-title: 完成挑戰! challenge-subtitle: '[friendlyName]' -# Title and subtitle my contain variable in [] that will be replaced with proper message from level object. -# [friendlyName] will be replaced with level friendly name. -# [rewardText] will be replaced with level reward text. - level-title: '成功挑戰級別' + level-title: 完成等級! level-subtitle: '[friendlyName]' messages: - admin: - hit-things: '點擊物品將它們添加到所需的事物列表中。 完成後右鍵單擊。' - you-added: '你在挑戰中添加了一個[thing]' - challenge-created: '[challenge]created!' - complete-wipe: '希望你有備份,因爲你已經創建了所有Challenges Addon數據庫!' - completed: '已爲[player]完成挑戰[name]!' - already-completed: '這個挑戰已經完成' - you-completed-challenge: '你已經完成了 [value] 挑戰!' - you-repeated-challenge: '你已經重複完成了 [value] 挑戰!' - you-repeated-challenge-multiple: '你重複完成了 [value] 挑戰 [count] 次!' - no-reward-this-time: "運氣不佳——這次沒有獎勵!" - you-completed-level: '你完成了 [value] 級別!' - name-has-completed-challenge: '[name] 已完成 [value] 挑戰!' - name-has-completed-level: '[name] 已完成 [value] 挑戰級別!' - import-levels: '開始導入挑戰級別' - import-challenges: '開始導入挑戰' - no-levels: '警告: challenges.yml文件中沒有定義挑戰級別' - import-number: '導入 [number] 個挑戰' - load-skipping: '"[value]" 已存在 - 跳過' - load-overwriting: '覆蓋 "[value]"' - load-add: '添加新的對象: [value]' - defaults-file-overwrite: 'defaults.json存在。 它將被覆蓋。' - defaults-file-completed: 'defaults.json文件填充了來自[world]的挑戰!' - completed: 你完成了 [name] 的挑戰 for [player]! + completed: 你已為 [player] 完成挑戰 [name]! already-completed: 此挑戰已完成! - reset: 你重設了 [name] 的挑戰 for [player]! - reset-all: 所有 [player] 的挑戰已重設! + reset: 你已重設 [player] 的挑戰 [name]! + reset-all: 已重設 [player] 的所有挑戰! not-completed: 此挑戰尚未完成! - migrate-start: 開始遷移挑戰附加元件資料。 - migrate-end: 挑戰附加元件資料已更新至新格式。 - migrate-not: 所有資料都有效。 + migrate-start: 開始遷移 Challenges 附加元件資料。 + migrate-end: Challenges 附加元件資料已更新為新格式。 + migrate-not: 所有資料皆有效。 start-downloading: 開始下載並匯入挑戰圖書館。 + you-completed-challenge: 你已完成 [value] 挑戰! + you-repeated-challenge: 你再次完成了 [value] 挑戰! + you-repeated-challenge-multiple: 你已重複完成 [value] 挑戰 [count] 次! + you-completed-level: 你已完成 [value] 等級! + name-has-completed-challenge: [name] 已完成 [value] 挑戰! + name-has-completed-level: [name] 已完成 [value] 等級! + load-skipping: '"[value]" 已存在,已略過。' + load-overwriting: '正在覆寫「[value]」' + load-add: '新增物件:[value]' errors: - no-name: '缺少挑戰名稱' - unknown-challenge: '未知挑戰' - unique-id: 'UniqueID "[id]" 無效.' - wrong-icon: '給定材料“[value]”無效且不能用作圖標。' - not-valid-integer: '給定整數“[value]”無效!|值應介于[min]和[max]之間。' - not-a-integer: '給定值“[value]”不是整數!' - not-deployed: '未開啓挑戰!' - not-on-island: '你必須在你的島上做到這一點!' - challenge-level-not-available: '你沒有解鎖挑戰級別來完成這個挑戰。' - not-repeatable: '這個挑戰是不可重複的!' - wrong-environment: '你在錯誤的環境中!' - not-enough-items: '你沒有足够的[items]來完成這個挑戰!' - not-close-enough: '你必須站在擁有[number]個任務需求方塊的旁邊.' - you-still-need: '你還需要 [amount] x [item]' - missing-addon: '無法完成挑戰。 缺少必需的插件或組件。' - incorrect: '無法完成挑戰。 要求不正確。' - not-enough-money: '您的帳戶必須有[value]金錢才能完成挑戰。.' - not-enough-experience: '必須有[value]EXP才能完成挑戰' - island-level: '你的島嶼等級需要達到[number]才能完成挑戰' - import-no-file: '找不到challenge.yml文件導入!' - no-load: '錯誤:無法加載challenge.yml。 [message]' - load-error: '錯誤:無法加載 [value].' - no-rank: "你沒有等級可以做到這一點." - cannot-remove-items: '有些物品無法從你的背包中删除!' - exist-challenges-or-levels: '在你的世界裏已經存在挑戰。 無法繼續!' - defaults-file-exist: 'defaults.json已經存在。 使用覆蓋模式替換它!' - defaults-file-error: '創建defaults.json文件時出錯! 檢查控制台!' - no-challenges: '當前世界沒有實施挑戰!' - no-challenges-admin: '當前世界沒有實施挑戰!你應該使用 /[label] challenges 添加他們!' - missing-level: '挑戰級別[level]未在數據庫中定義. 可能會出現錯誤!' - missing-arguments: '命令缺少參數.' - import-failed: 無法匯入挑戰:[message]。查看伺服器主控台瞭解詳情。 - no-multiple-permission: 你沒有權限一次完成此挑戰多次。 - invalid-level: 等級 [level] 包含無效資料且不會從資料庫載入! - invalid-challenge: 挑戰 [challenge] 包含無效資料且不會從資料庫載入! - no-library-entries: 找不到圖書館項目。沒有可顯示的內容。 - not-hooked: 挑戰附加元件無法找到任何 GameMode。 - timeout: 此挑戰需要 [timeout] 秒的等待時間。你必須等待 [wait-time] 才能再次完成它。 - requirement-not-met: 此挑戰需要 [number] 的 [statistic]。你只有 [value]。 - requirement-not-met-entity: 此挑戰需要 [entity] 的 [statistic] 為 [number]。你只有 [value]。 - requirement-not-met-material: 此挑戰需要 [material] 的 [statistic] 為 [number]。你只有 [value]。 - no-team: 這是團隊挑戰。你必須有團隊才能完成它! - insufficient-team: 此團隊挑戰需要 [number] 個團隊成員在線。只有 [online] 在線。 - member-missing-share: [name] 沒有他們的份額([amount] x [item])用於此團隊挑戰。 - wrong-biome: "你必須站在 [biome] 生態域中才能完成此挑戰!" - materials: - any: '任何 ' - all_hanging_signs: - name: 任何懸掛式告示牌 - all_signs: - name: 任何告示牌 - conversations: - prefix: [BentoBox]: - confirm-string: true, on, yes, confirm, y, valid, correct - deny-string: false, off, no, deny, n, invalid, incorrect - cancel-string: cancel - exit-string: cancel, exit, quit - cancelled: 對話已取消! - input-number: 請在聊天中輸入數字。 - input-seconds: 請在聊天中輸入秒數。 - numeric-only: 給定的 [value] 不是數字! - not-valid-value: "輸入的數字 [value] 無效。必須在 [min] 到 [max] 之間(含邊界值)。" - user-data-removed: 所有 [gamemode] 的使用者資料已從資料庫中清除。 - confirm-user-data-deletion: 請確認你想清除 [gamemode] 的使用者資料庫。 - challenge-data-removed: 所有 [gamemode] 的挑戰資料已從資料庫中清除。 - confirm-challenge-data-deletion: 請確認你想清除 [gamemode] 的挑戰資料庫。 - all-data-removed: 所有 [gamemode] 的附加元件資料已從資料庫中清除。 - confirm-all-data-deletion: 請確認你想清除 [gamemode] 的附加元件資料。 - write-name: 請在聊天中輸入名稱。 - new-object-created: [gamemode] 的新物件已建立。 - object-already-exists: 物件 [id] 已存在。請選擇不同的名稱。 - invalid-challenge: 挑戰 [challenge] 包含無效資料且無法部署! - name-changed: 成功:名稱已更新。 - write-description: 請在聊天中輸入新描述。在新行上輸入「退出」以完成。 - description-changed: 成功:描述已更新。 - write-permissions: 請在聊天中逐行輸入所需的權限。在新行上輸入「退出」以完成。 - permissions-changed: 成功:挑戰權限已更新。 - write-reward-text: 請在聊天中輸入新的獎勵文字。在新行上輸入「退出」以完成。 - reward-text-changed: 成功:獎勵文字已更新。 - write-repeat-reward-text: 請在聊天中輸入新的重複獎勵文字。在新行上輸入「退出」以完成。 - repeat-reward-text-changed: 成功:重複獎勵文字已更新。 - write-reward-commands: 請在聊天中的每一行上輸入新的獎勵指令。在新行上輸入「退出」以完成。 - reward-commands-changed: 成功:獎勵指令已更新。 - write-repeat-reward-commands: 請在聊天中的每一行上輸入新的重複獎勵指令。在新行上輸入「退出」以完成。 - repeat-reward-commands-changed: 成功:重複獎勵指令已更新。 - challenge-removed: 挑戰 [challenge] for [gamemode] 已從資料庫中移除。 - confirm-challenge-deletion: 請確認你想從資料庫中移除 [challenge] for [gamemode]。 - level-removed: 等級 [level] for [gamemode] 已從資料庫中移除。 - confirm-level-deletion: 請確認你想從資料庫中移除 [level] for [gamemode]。 - start-downloading: 開始下載並匯入挑戰圖書館。 - written-text: 輸入文字: - confirm-data-replacement: 請確認你想將目前的挑戰替換為新的。 - new-challenges-imported: 成功:[gamemode] 的新挑戰已匯入。 - exported-file-name: 請輸入已匯出之資料庫檔案的檔案名稱。(輸入「取消」退出) - database-export-completed: 成功:[world] 的資料庫匯出已完成。已產生檔案 [file]。 - file-name-exist: 名為「[id]」的檔案已存在。無法覆蓋。 - write-search: 請輸入搜尋值。(輸入「取消」退出) - search-updated: 搜尋值已更新。 - enter-formula: "輸入使用 PAPI 佔位符和符號 =,<>,<+,>=, ==, !=, AND, OR 的公式。\n範例:%my_lifetime_count% >= 1000 AND %island_level% >= 100" - confirm-instruction: "在聊天中輸入'confirm'以繼續,或輸入'cancel'以取消。" - input-repeat-count: "請在聊天中輸入重複次數。輸入 0 表示無限次。" + no-name: 缺少挑戰名稱。 + unknown-challenge: 未知的挑戰。 + not-valid-integer: |- + 輸入的整數「[value]」無效! + 必須介於 [min] 與 [max] 之間。 + not-deployed: 此挑戰尚未部署! + not-on-island: 你必須位於自己的島嶼上才能這麼做! + challenge-level-not-available: 你尚未解鎖完成此挑戰所需的等級。 + not-repeatable: 此挑戰不可重複完成! + wrong-environment: 你目前所在的維度無法完成此挑戰! + not-enough-items: 你沒有足夠的 [items] 可完成此挑戰! + not-close-enough: 你必須站在所有需求方塊 [number] 格範圍內。 + you-still-need: 你還需要 [amount] x [item] + missing-addon: 無法完成挑戰:缺少所需的附加元件或外掛。 + incorrect: 無法完成挑戰:尚未符合需求條件。 + not-enough-money: 你的帳戶至少需要有 [value] 才能完成此挑戰。 + not-enough-experience: 你至少需要 [value] 點經驗值才能完成此挑戰。 + island-level: 你的島嶼至少需要達到等級 [number] 才能完成此挑戰! + no-load: '錯誤:無法載入 [file]。錯誤:[message]。' + load-error: '錯誤:無法載入 [value]。' + import-failed: '無法匯入挑戰:[message]。請查看伺服器主控台以取得詳細資訊。' + no-rank: 你的權限等級不足,無法執行此操作。 + cannot-remove-items: 部分物品無法從你的背包中移除! + exist-challenges-or-levels: 此世界已存在挑戰或等級,無法繼續! + no-challenges: 此世界尚未設定挑戰! + no-challenges-admin: 此世界尚未設定挑戰!請使用 /[command] 新增挑戰! + missing-arguments: 指令缺少必要參數。 + no-multiple-permission: 你沒有一次完成多次挑戰的權限。 + invalid-level: 等級 [level] 包含無效資料,因此不會從資料庫載入! + invalid-challenge: 挑戰 [challenge] 包含無效資料,因此不會從資料庫載入! + no-library-entries: 找不到任何圖書館項目,沒有可顯示的內容。 + not-hooked: Challenges 附加元件找不到任何 GameMode。 + timeout: 此挑戰完成後需等待 [timeout] 才能再次完成,你還需要等待 [wait-time]。 + requirement-not-met: 此挑戰需要 [statistic] 達到 [number],你目前只有 [value]。 + requirement-not-met-entity: 此挑戰需要 [entity] 的 [statistic] 達到 [number],你目前只有 [value]。 + requirement-not-met-material: 此挑戰需要 [material] 的 [statistic] 達到 [number],你目前只有 [value]。 + no-team: 這是一項隊伍挑戰,你必須加入隊伍才能完成! + insufficient-team: 此隊伍挑戰需要至少 [number] 位隊伍成員在線,目前只有 [online] 位在線。 + member-missing-share: [name] 尚未提供他應負責的份額([amount] x [item])。 +# # Showcase for manual material translation +# materials: +# # Names should be lowercase. +# cobblestone: "Cobblestone" +# # Also supports descriptions. +# stone: +# name: "Stone" +# description: "" +# item-stacks: +# # Non-specific item meta translations. +# # TYPE is the item type +# # META is a content of item meta. +# generic: "[type] [meta]" +# # Non-specific meta translations. Will replace [meta] +# meta: +# upgraded: "Upgraded" +# extended: "Extended" +# potion-meta: "[type] [upgraded] [extended]" +# # Be aware, enchants are always listed below item in separate line. +# enchant-meta: " - [type] [level]" +# skull-meta: ": [player-name]" +# book-meta: "[title] [author]" +# # Custom Enchantment Translation. +# enchant: +# menting: "Mending" +# unbreaking: "Unbreaking" +# # Custom Potion Translation. +# potion-type: +# water_breathing: "Water Breathing" +# # You can also create specific item translations +# # Like translate all potions. +# potion: +# # This will overwrite generic translation. +# name: "[type] [upgraded] [extended]" +# # Type is either specific translation or potion effect. +# uncraftable: "Uncraftable" +# water: "Water" +# mundane: "Mundane" +# thick: "Thick" +# awkward: "Awkward" +# night_vision: "Potion of Night Vision" +# invisibility: "Potion of Invisibility" +# jump: "Potion of Leaping" +# fire_resistance: "Potion of Fire Resistance" +# speed: "Potion of Swiftness" +# slowness: "Potion of Slowness" +# water_breathing: "Potion of Water Breathing" +# instant_heal: "Potion of Healing" +# instant_damage: "Potion of Harming" +# poison: "Potion of Poison" +# regen: "Potion of Regeneration" +# strength: "Potion of Strength" +# weakness: "Potion of Weakness" +# luck: "Potion of Luck" +# turtle_master: "Potion of Turtle Master" +# slow_falling: "Potion of Slow Falling" +# stone_shovel: +# # This will mean that only stone shovels will not show +# # meta information. +# name: "[type]" +# +# # Showcase how to support multi-linguistic challenges +# challenges: +# # Database ID name. +# example_challenge_id: +# name: "Translated Name" +# description: |- +# Translated Custom +# description +# reward-text: |- +# Translated Reward +# text +# repeat-reward-text: |- +# Translated Repeat +# Reward text +# levels: +# # Database ID name. +# example_level_id: +# name: "Translated Name" +# description: |- +# Translated Custom +# description +# reward-text: |- +# Translated Reward +# text protection: flags: CHALLENGES_ISLAND_PROTECTION: - description: "切換誰可以\n挖槽挑戰" - name: "挑戰保護" + description: |- + 設定哪些人 + 可以完成挑戰。 + name: 挑戰保護 CHALLENGES_WORLD_PROTECTION: - description: "爲玩家啓用/禁用\n要求他們在他們的島嶼上\n才能完成挑戰." - name: "挑戰島嶼限制" - hint: "請在自己的島嶼完成挑戰!" -version: 11 + description: |- + 啟用或停用 + 玩家必須位於 + 自己的島嶼上 + 才能完成挑戰的限制。 + name: 挑戰島嶼限制 + hint: 島嶼外無法完成挑戰 +version: 12 From 3bb60dacdc05b14918144c27d2eaa8e52e5a551f Mon Sep 17 00:00:00 2001 From: qwe664 <93234700+qwe664@users.noreply.github.com> Date: Mon, 10 Aug 2026 09:04:53 +0800 Subject: [PATCH 03/15] Update zh-TW.yml: complete translation coverage for v1.8.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Overview Completes the Traditional Chinese (zh-TW) translation coverage for Challenges v1.8.0. The existing translation was based on the v1.7.0 English source, so text introduced in v1.8.0 was not yet translated. ## What's added v1.8.0 introduced a biome requirement/selection feature. This PR adds the 32 corresponding translation entries, covering: - `challenges.conversations.*` — conversation confirmation prompts - `challenges.errors.wrong-biome` — wrong biome error message - `challenges.gui.buttons.biome.*` — biome selection button - `challenges.gui.buttons.open_anywhere.*` — "open GUI anywhere" toggle - `challenges.gui.buttons.repeat_count.value-infinite` — infinite repeat count display - `challenges.gui.buttons.repeat_reward_island_level.*` / `reward_island_level.*` — island level reward settings - `challenges.gui.buttons.required_biomes.*` — required biomes list - `challenges.gui.buttons.reward_chance.*` — reward chance settings - `challenges.gui.buttons.toggle-undeployed.*` — undeployed challenges visibility toggle - `challenges.gui.descriptions.challenge.requirements.island.biome-*` — biome requirement descriptions - `challenges.gui.titles.biome-selector` — biome selector title - `challenges.messages.no-reward-this-time` — no-reward message ## Verification Diffed the updated zh-TW.yml against the official en-US.yml (v1.8.0, 905 keys total) key-by-key. Confirmed 100% coverage with no missing or stray keys, and validated the YAML syntax. New entries follow the existing translation's established terminology (e.g. consistent use of existing terms like "部署" for deploy, "島嶼等級" for island level, "重複次數" for repeat count). --- src/main/resources/locales/zh-TW.yml | 1208 +++++++++++++------------- 1 file changed, 615 insertions(+), 593 deletions(-) diff --git a/src/main/resources/locales/zh-TW.yml b/src/main/resources/locales/zh-TW.yml index df653b58..0dd6cac8 100644 --- a/src/main/resources/locales/zh-TW.yml +++ b/src/main/resources/locales/zh-TW.yml @@ -6,15 +6,13 @@ meta: authors: - BONNe - challenges: materials: - any: '任何' + any: 任何 all_hanging_signs: name: 任何懸掛式告示牌 all_signs: name: 任何告示牌 - commands: admin: main: @@ -44,13 +42,9 @@ challenges: parameters: [count] gui: titles: - # The title for the Main GUI player-gui: 挑戰選單 - # The title for the Main GUI gamemode-gui: 選擇遊戲模式 - # The title for the Multiple Completion GUI multiple-gui: 要完成幾次? - # GUI titles below are visible just for Admins. admin-gui: 挑戰管理選單 edit-challenge: 編輯 [challenge] edit-level: 編輯 [level] @@ -73,130 +67,123 @@ challenges: challenge-selector: 挑戰選擇器 statistic-selector: 統計資料選擇器 environment-selector: 維度選擇器 + biome-selector: 生態域選擇器 buttons: - # Button in the Challenges GUI that allows to select free challenges. free-challenges: name: 自由挑戰 - description: |- - 顯示所有 - 自由挑戰 -# Button that is used to return to previous GUI or exit it completely. + description: '顯示所有 + + 自由挑戰' return: name: 返回 - description: |- - 返回上一個選單 - 或離開選單 -# Button that is used in multi-page GUIs which allows to return to previous page. + description: '返回上一個選單 + + 或離開選單' previous: name: 上一頁 description: 切換至第 [number] 頁 -# Button that is used in multi-page GUIs which allows to go to next page. next: name: 下一頁 description: 切換至第 [number] 頁 -# Button that allows to reduce number reduce: name: 減少 description: 減少 [number] -# Button that allows to increase number increase: name: 增加 description: 增加 [number] -# Button that displays and allows completing challenge accept: name: 完成 - description: |- - 完成挑戰 - [number] 次 -# Button that allows to quit the current gui. + description: '完成挑戰 + + [number] 次' quit: name: 離開 description: 離開選單。 -# All following buttons are mainly for Admin GUI. complete_user_challenges: name: 完成玩家挑戰 - description: |- - 選擇一位玩家, - 並替其完成挑戰。 + description: '選擇一位玩家, + + 並替其完成挑戰。' reset_user_challenges: name: 重設玩家挑戰 - description: |- - 選擇一位玩家, - 並重設其挑戰。 + description: '選擇一位玩家, + + 並重設其挑戰。' add_challenge: name: 建立挑戰 - description: |- - 開始建立 - 新的挑戰。 + description: '開始建立 + + 新的挑戰。' add_level: name: 建立等級 - description: |- - 開始建立 - 新的等級。 + description: '開始建立 + + 新的等級。' edit_challenge: name: 編輯挑戰 - description: |- - 選擇並編輯 - 一項挑戰。 + description: '選擇並編輯 + + 一項挑戰。' edit_level: name: 編輯等級 - description: |- - 選擇並編輯 - 一個等級。 + description: '選擇並編輯 + + 一個等級。' delete_challenge: name: 刪除挑戰 - description: |- - 選擇並刪除 - 一項挑戰。 + description: '選擇並刪除 + + 一項挑戰。' delete_level: name: 刪除等級 - description: |- - 選擇並刪除 - 一個等級。 + description: '選擇並刪除 + + 一個等級。' edit_settings: name: 設定 - description: |- - 檢視並編輯 - 附加元件設定。 + description: '檢視並編輯 + + 附加元件設定。' complete_wipe: name: 完全清除 - description: |- - 完整清除挑戰 + description: '完整清除挑戰 + 附加元件資料庫, - 包含所有玩家資料。 + + 包含所有玩家資料。' challenge_wipe: name: 清除挑戰資料 - description: |- - 完整清除資料庫中的 - 所有挑戰與等級。 + description: '完整清除資料庫中的 + + 所有挑戰與等級。' user_wipe: name: 清除玩家資料 - description: |- - 完整清除資料庫中的 - 所有玩家資料。 + description: '完整清除資料庫中的 + + 所有玩家資料。' library: name: 圖書館 - description: |- - 開啟公開的 - 挑戰圖書館。 - downloading: |- - 已提出下載 - 圖書館請求…… + description: '開啟公開的 + + 挑戰圖書館。' + downloading: '已提出下載 + + 圖書館請求……' import_database: name: 匯入資料庫 - description: |- - 匯入已匯出的 - 挑戰資料庫。 + description: '匯入已匯出的 + + 挑戰資料庫。' import_template: name: 匯入範本 - description: |- - 匯入包含挑戰的 - 範本檔案。 + description: '匯入包含挑戰的 + + 範本檔案。' export_challenges: name: 匯出挑戰 - description: |- - 將資料庫匯出至 - 本機檔案。 + description: '將資料庫匯出至 + + 本機檔案。' properties: name: 屬性 description: 檢視所有主要屬性。 @@ -208,291 +195,324 @@ challenges: description: 檢視獎勵屬性。 hide_reward_items: name: 隱藏獎勵物品 - description: |- - 切換是否在選單中 - 顯示獎勵物品。 + description: '切換是否在選單中 + + 顯示獎勵物品。' hide: 隱藏 show: 顯示 deployed: name: 部署 - description: |- - 切換此挑戰是否已部署, + description: '切換此挑戰是否已部署, + 並允許玩家 - 完成。 + + 完成。' enabled: 已啟用 disabled: 已停用 name: name: 名稱 - description: |- - 允許你變更 - 顯示名稱。 - value: '目前:[name]' + description: '允許你變更 + + 顯示名稱。' + value: 目前:[name] remove_on_complete: name: 完成後隱藏 - description: |- - 切換玩家完成挑戰後, + description: '切換玩家完成挑戰後, + 是否將此挑戰 - 隱藏。 + + 隱藏。' enabled: 已啟用 disabled: 已停用 team_challenge: name: 團隊挑戰 - description: |- - 切換此挑戰是否為團隊挑戰。 + description: '切換此挑戰是否為團隊挑戰。 + 團隊挑戰需要有隊伍, - 並於整座島嶼共用完成狀態與冷卻時間。 + + 並於整座島嶼共用完成狀態與冷卻時間。' enabled: 已啟用 disabled: 已停用 team_presence: name: 團隊在線率 - description: |- - 完成此挑戰時, + description: '完成此挑戰時, + 隊伍中必須在線的 + 成員百分比。 - 設為 0 可停用此限制。 - value: '目前:[number]%' + + 設為 0 可停用此限制。' + value: 目前:[number]% aggregate_team: name: 團隊合併計算 - description: |- - 將所有在線成員的 + description: '將所有在線成員的 + 需求物品/統計資料合併計算 - (共同貢獻、共同努力)。 + + (共同貢獻、共同努力)。' enabled: 已啟用 disabled: 已停用 per_member: name: 每位成員皆需貢獻 - description: |- - 每位在線成員都必須繳交 + description: '每位在線成員都必須繳交 + 自己的份額(需求數量為 - 團隊總需求,平均分配給在線成員)。 + + 團隊總需求,平均分配給在線成員)。' enabled: 已啟用 disabled: 已停用 hide_if_no_team: name: 無隊伍時隱藏 - description: |- - 啟用後,沒有隊伍的玩家 + description: '啟用後,沒有隊伍的玩家 + 將完全看不到此挑戰。 - 停用後則仍會顯示,但無法完成。 + + 停用後則仍會顯示,但無法完成。' enabled: 已啟用 disabled: 已停用 description: name: 描述 - description: |- - 設定此挑戰的描述。 - 需自行加入色彩代碼。 - value: '目前描述:' + description: '設定此挑戰的描述。 + + 需自行加入色彩代碼。' + value: 目前描述: environment: name: 維度 - description: |- - 允許你將此挑戰 - 限制於指定維度。 + description: '允許你將此挑戰 + + 限制於指定維度。' enabled: disabled: order: name: 排序 - description: |- - 允許你調整 + description: '允許你調整 + 物件的排序順序。 + 若排序值相同, + 則依照其 - 唯一 ID 名稱排序。 - value: '目前排序:[number]' + + 唯一 ID 名稱排序。' + value: 目前排序:[number] icon: name: 圖示 - description: |- - 允許你變更 - 此挑戰的圖示。 + description: '允許你變更 + + 此挑戰的圖示。' locked_icon: name: 鎖定圖示 - description: |- - 允許你變更 - 鎖定狀態的等級圖示。 + description: '允許你變更 + + 鎖定狀態的等級圖示。' required_permissions: name: 需求權限 - description: |- - 允許你修改 + description: '允許你修改 + 完成此挑戰 - 所需的權限。 - title: '權限:' + + 所需的權限。' + title: 權限: permission: ' - [permission]' none: 尚未設定任何權限。 remove_entities: name: 移除實體 - description: |- - 切換完成挑戰後, + description: '切換完成挑戰後, + 是否將所需實體 - 自世界中移除。 + + 自世界中移除。' enabled: 已啟用 disabled: 已停用 required_entities: name: 需求實體 - description: |- - 允許你修改 + description: '允許你修改 + 完成此挑戰 - 所需的實體。 - title: '實體:' + + 所需的實體。' + title: 實體: list: ' - [number] x [entity]' none: 尚未新增任何實體。 remove_blocks: name: 移除方塊 - description: |- - 切換完成挑戰後, + description: '切換完成挑戰後, + 是否將所需方塊 - 自世界中移除。 + + 自世界中移除。' enabled: 已啟用 disabled: 已停用 required_blocks: name: 需求方塊 - description: |- - 允許你修改 + description: '允許你修改 + 完成此挑戰 - 所需的方塊。 - title: '方塊:' + + 所需的方塊。' + title: 方塊: list: ' - [number] x [block]' none: 尚未新增任何方塊。 required_statistics: name: 需求統計資料 - description: |- - 允許你修改 + description: '允許你修改 + 完成此挑戰 - 所需的統計資料。 - title: '統計資料:' + + 所需的統計資料。' + title: 統計資料: list: ' - [name]' none: 尚未新增任何統計資料。 required_advancements: name: 需求進度 - description: |- - 允許你修改 + description: '允許你修改 + 完成此挑戰 - 所需的進度。 - title: '進度:' + + 所需的進度。' + title: 進度: list: ' - [name]' none: 尚未新增任何進度。 search_radius: name: 搜尋半徑 - description: |- - 允許你修改 + description: '允許你修改 + 以玩家為中心偵測 - 方塊及/或實體的半徑。 - value: '目前距離:[number]' + + 方塊及/或實體的半徑。' + value: 目前距離:[number] remove_items: name: 移除物品 - description: |- - 切換完成挑戰後, + description: '切換完成挑戰後, + 是否從玩家背包中 - 移除所需物品。 + + 移除所需物品。' enabled: 已啟用 disabled: 已停用 required_items: name: 需求物品 - description: |- - 允許你修改 + description: '允許你修改 + 完成此挑戰 - 所需的物品。 - title: '物品:' + + 所需的物品。' + title: 物品: list: ' - [number] x [item]' none: 尚未新增任何物品。 add_ignored_meta: name: 新增忽略中繼資料 - description: |- - 允許你指定哪些物品 + description: '允許你指定哪些物品 + 應忽略其 - 中繼資料。 - title: '物品:' + + 中繼資料。' + title: 物品: list: ' - [number] x [item]' none: 尚未新增任何物品。 remove_ignored_meta: name: 移除忽略中繼資料 - description: |- - 移除會忽略 - 中繼資料的物品。 + description: '移除會忽略 + + 中繼資料的物品。' remove_experience: name: 移除經驗值 - description: |- - 切換完成挑戰後, + description: '切換完成挑戰後, + 是否扣除玩家 - 所需的經驗值。 + + 所需的經驗值。' enabled: 已啟用 disabled: 已停用 required_experience: name: 需求經驗值 - description: |- - 允許你修改 + description: '允許你修改 + 玩家所需的 - 經驗值。 - value: '目前經驗值:[number]' + + 經驗值。' + value: 目前經驗值:[number] required_level: name: 需求島嶼等級 - description: |- - 允許你修改 + description: '允許你修改 + 完成此挑戰 - 所需的島嶼等級。 - value: '目前等級:[number]' + + 所需的島嶼等級。' + value: 目前等級:[number] required_materialtags: name: 需求方塊群組 - description: |- - 允許你修改 + description: '允許你修改 + 完成此挑戰 - 所需的方塊群組。 - title: '方塊群組:' + + 所需的方塊群組。' + title: 方塊群組: list: ' - [number] x [tag]' none: 尚未新增任何方塊群組。 required_entitytags: name: 需求實體群組 - description: |- - 允許你修改 + description: '允許你修改 + 完成此挑戰 - 所需的實體群組。 - title: '實體群組:' + + 所需的實體群組。' + title: 實體群組: list: ' - [number] x [tag]' none: 尚未新增任何實體群組。 remove_money: name: 扣除金錢 - description: |- - 切換完成挑戰後, + description: '切換完成挑戰後, + 是否從玩家帳戶 - 扣除所需金額。 + + 扣除所需金額。' enabled: 已啟用 disabled: 已停用 required_money: name: 需求金額 - description: |- - 允許你修改 + description: '允許你修改 + 完成挑戰所需的 - 玩家帳戶金額。 - value: '目前數值:[number]' + + 玩家帳戶金額。' + value: 目前數值:[number] required_papi: name: 需求 PAPI - description: |- - 檢查一個可包含 + description: '檢查一個可包含 + PAPI Placeholder - 以及數學、邏輯運算的公式。 - value: '公式:[formula]' + + 以及數學、邏輯運算的公式。' + value: 公式:[formula] statistic: name: 統計資料 - description: |- - 允許你修改 + description: '允許你修改 + 此挑戰所檢查的 - 統計資料類型。 - value: '目前數值:[statistic]' + + 統計資料類型。' + value: 目前數值:[statistic] statistic_amount: name: 目標數值 - description: |- - 允許你修改 + description: '允許你修改 + 必須達成的 - 統計資料目標值。 - value: '目前數值:[number]' + + 統計資料目標值。' + value: 目前數值:[number] add_statistic: name: 新增統計資料 - description: |- - 允許你新增 - 統計資料至清單。 + description: '允許你新增 + + 統計資料至清單。' remove_statistic: name: 移除統計資料 - description: |- - 允許你移除 + description: '允許你移除 + 清單中的 - 統計資料。 + + 統計資料。' enabled: 已啟用 disabled: 已停用 advancement: @@ -500,113 +520,132 @@ challenges: description: '[description]' add_advancement: name: 新增進度 - description: |- - 允許你新增 - 進度至清單。 + description: '允許你新增 + + 進度至清單。' remove_advancement: name: 移除進度 - description: |- - 允許你移除 + description: '允許你移除 + 清單中的 - 進度。 + + 進度。' enabled: 已啟用 disabled: 已停用 statistic_blocks: name: 目標方塊 - description: |- - 允許你修改 + description: '允許你修改 + 統計資料的 - 目標方塊。 - value: '目前方塊:[block]' + + 目標方塊。' + value: 目前方塊:[block] statistic_items: name: 目標物品 - description: |- - 允許你修改 + description: '允許你修改 + 統計資料的 - 目標物品。 - value: '目前物品:[item]' + + 目標物品。' + value: 目前物品:[item] statistic_entities: name: 目標實體 - description: |- - 允許你修改 + description: '允許你修改 + 統計資料的 - 目標實體。 - value: '目前實體:[entity]' + + 目標實體。' + value: 目前實體:[entity] reward_text: name: 獎勵文字 - description: |- - 設定獎勵文字。 - 需自行加入色彩代碼。 - value: '目前文字:' + description: '設定獎勵文字。 + + 需自行加入色彩代碼。' + value: 目前文字: repeat_reward_text: name: 重複獎勵文字 - description: |- - 設定此挑戰的 + description: '設定此挑戰的 + 重複獎勵文字。 - 需自行加入色彩代碼。 - value: '目前文字:' + + 需自行加入色彩代碼。' + value: 目前文字: reward_items: name: 獎勵物品 description: 允許你修改獎勵物品。 - title: '物品:' + title: 物品: list: ' - [number] x [item]' none: 尚未新增任何物品。 repeat_reward_items: name: 重複獎勵物品 - description: |- - 允許你修改 - 此挑戰的重複獎勵物品。 - title: '物品:' + description: '允許你修改 + + 此挑戰的重複獎勵物品。' + title: 物品: list: ' - [number] x [item]' none: 尚未新增任何物品。 reward_experience: name: 獎勵經驗值 - description: |- - 允許你修改 - 玩家獲得的獎勵經驗值。 - value: '獎勵經驗值:[number]' + description: '允許你修改 + + 玩家獲得的獎勵經驗值。' + value: 獎勵經驗值:[number] repeat_reward_experience: name: 重複獎勵經驗值 - description: |- - 允許你修改 - 玩家獲得的重複獎勵經驗值。 - value: '獎勵經驗值:[number]' + description: '允許你修改 + + 玩家獲得的重複獎勵經驗值。' + value: 獎勵經驗值:[number] reward_money: name: 獎勵金額 description: 允許你修改獎勵金額。 - value: '目前數值:[number]' + value: 目前數值:[number] repeat_reward_money: name: 重複獎勵金額 - description: |- - 允許你修改 - 此挑戰的重複獎勵金額。 - value: '目前數值:[number]' + description: '允許你修改 + + 此挑戰的重複獎勵金額。' + value: 目前數值:[number] reward_commands: name: 獎勵指令 - description: |- - 設定獎勵指令。 + description: '設定獎勵指令。 + 提示: + 指令前不需要加上「/」, + 系統會自動補上。 + 預設會由伺服器執行指令。 + 若在開頭加入 [SELF], + 則改由玩家自行執行。 + 也支援 [player] Placeholder, - 會自動替換為完成挑戰的玩家名稱。 - value: '目前指令:' + + 會自動替換為完成挑戰的玩家名稱。' + value: 目前指令: repeat_reward_commands: name: 重複獎勵指令 - description: |- - 設定此挑戰的重複獎勵指令。 + description: '設定此挑戰的重複獎勵指令。 + 提示: + 指令前不需要加上「/」, + 系統會自動補上。 + 預設會由伺服器執行指令。 + 若在開頭加入 [SELF], + 則改由玩家自行執行。 + 也支援 [player] Placeholder, - 會自動替換為完成挑戰的玩家名稱。 - value: '目前指令:' + + 會自動替換為完成挑戰的玩家名稱。' + value: 目前指令: repeatable: name: 可重複完成 description: 切換此挑戰是否可重複完成。 @@ -614,137 +653,153 @@ challenges: disabled: 已停用 repeat_count: name: 重複次數 - description: |- - 允許你修改 - 此挑戰可重複完成的次數。 - value: '目前數值:[number]' + description: '允許你修改 + + 此挑戰可重複完成的次數。' + value: 目前數值:[number] + value-infinite: 目前數值:[number] (無限) cool_down: name: 冷卻時間 - description: |- - 允許你修改 + description: '允許你修改 + 可重複完成挑戰之間 - 所需等待的時間(秒)。 - value: '目前數值:[time]' + + 所需等待的時間(秒)。' + value: 目前數值:[time] challenges: name: 挑戰 - description: |- - 檢視指派至 - 此等級的挑戰。 + description: '檢視指派至 + + 此等級的挑戰。' waiver_amount: name: 可略過數量 - description: |- - 允許你設定可未完成 + description: '允許你設定可未完成 + 多少項挑戰即可解鎖 - 下一個等級。 - value: '目前數值:[number]' + + 下一個等級。' + value: 目前數值:[number] add_challenges: name: 新增挑戰 - description: |- - 允許你選擇並新增 - 挑戰至此等級。 + description: '允許你選擇並新增 + + 挑戰至此等級。' remove_challenges: name: 移除挑戰 - description: |- - 允許你選擇並移除 - 此等級中的挑戰。 + description: '允許你選擇並移除 + + 此等級中的挑戰。' reset_on_new: name: 建立新島時重設 - description: |- - 切換玩家離開島嶼 + description: '切換玩家離開島嶼 + 或建立新島時, - 是否重設挑戰。 + + 是否重設挑戰。' enabled: 已啟用 disabled: 已停用 broadcast: name: 廣播 - description: |- - 首次完成挑戰或等級時, - 向所有玩家廣播。 + description: '首次完成挑戰或等級時, + + 向所有玩家廣播。' enabled: 已啟用 disabled: 已停用 remove_completed: name: 隱藏已完成項目 - description: |- - 將已完成的挑戰 - 從選單中隱藏。 + description: '將已完成的挑戰 + + 從選單中隱藏。' enabled: 已啟用 disabled: 已停用 glow_completed: name: 已完成挑戰發光 - description: |- - 為已完成的挑戰 - 套用附魔發光效果。 + description: '為已完成的挑戰 + + 套用附魔發光效果。' enabled: 已啟用 disabled: 已停用 glow_completed_levels: name: 已完成等級發光 - description: |- - 為已完成的等級 - 套用附魔發光效果。 + description: '為已完成的等級 + + 套用附魔發光效果。' enabled: 已啟用 disabled: 已停用 store_history: name: 儲存歷史紀錄 - description: |- - 每次完成挑戰時 + description: '每次完成挑戰時 + 儲存內部歷史紀錄。 + 目前僅能於 - 資料庫中檢視。 + + 資料庫中檢視。' enabled: 已啟用 disabled: 已停用 data_per_island: name: 依島嶼儲存 - description: |- - 依照島嶼儲存 + description: '依照島嶼儲存 + 已完成的挑戰。 + 進度會與所有 - 隊伍成員共享。 + + 隊伍成員共享。' enabled: 已啟用 disabled: 已停用 show_title: name: 顯示標題 - description: |- - 完成挑戰或等級時 - 顯示標題。 + description: '完成挑戰或等級時 + + 顯示標題。' enabled: 已啟用 disabled: 已停用 gamemode_gui: name: 遊戲模式選擇選單 - description: |- - 啟用可透過 + description: '啟用可透過 + /challenges 指令開啟的 + 單一選單。 - (需重新啟動伺服器) + + (需重新啟動伺服器)' enabled: 已啟用 disabled: 已停用 locked_level_icon: name: 預設鎖定等級圖示 - description: |- - 所有鎖定等級的預設圖示。 - 每個等級皆可個別覆寫。 + description: '所有鎖定等級的預設圖示。 + + 每個等級皆可個別覆寫。' purge_history: name: 歷史紀錄保存天數 - description: |- - 設定玩家資料中 + description: '設定玩家資料中 + 歷史紀錄的保存天數。 + 設為 0 表示 - 永不刪除。 - value: '目前數值:[number]' + + 永不刪除。' + value: 目前數值:[number] title_showtime: name: 標題顯示時間 - description: |- - 設定標題 + description: '設定標題 + 顯示給玩家的 - Tick 數。 - value: '目前數值:[number]' + + Tick 數。' + value: 目前數值:[number] active_world_list: name: 僅顯示目前世界 - description: |- - 若已啟用遊戲模式選擇選單, + description: '若已啟用遊戲模式選擇選單, + 此設定決定選單 + 要顯示遊戲模式選擇, + 還是目前世界的挑戰。 - (需重新啟動伺服器) + + (需重新啟動伺服器)' enabled: 已啟用 disabled: 已停用 visibility_mode: @@ -757,38 +812,38 @@ challenges: toggleable: 允許切換 include_undeployed: name: 包含未部署挑戰 - description: |- - 設定未部署的挑戰 - 是否納入等級完成度計算。 + description: '設定未部署的挑戰 + + 是否納入等級完成度計算。' enabled: 已啟用 disabled: 已停用 download: name: 下載圖書館 - description: |- - 手動更新可用的 - 挑戰圖書館。 + description: '手動更新可用的 + + 挑戰圖書館。' enabled: 清除快取 disabled: 保留快取 language: name: 語言 - description: |- - 依語言篩選 - 挑戰圖書館。 - current: '目前顯示:[lang]' + description: '依語言篩選 + + 挑戰圖書館。' + current: 目前顯示:[lang] all: 全部 player: name: [name] - description: '島主:[owner]' - members: '島嶼成員:' + description: 島主:[owner] + members: 島嶼成員: member: - [name] - no-island: |- - 此玩家 - 沒有島嶼。 + no-island: '此玩家 + + 沒有島嶼。' player_list: name: 選擇玩家清單 - description: |- - 選擇要顯示的 - 玩家清單。 + description: '選擇要顯示的 + + 玩家清單。' enabled: disabled: online: 在線玩家 @@ -796,33 +851,35 @@ challenges: in_world: 世界中的玩家 add_block: name: 新增方塊 - description: |- - 允許你新增 - 方塊至清單。 + description: '允許你新增 + + 方塊至清單。' add_block_group: name: 新增方塊群組 - description: |- - 允許你新增 - 方塊群組至清單。 + description: '允許你新增 + + 方塊群組至清單。' remove_block: name: 移除方塊 - description: |- - 允許你移除 + description: '允許你移除 + 清單中的 - 方塊。 - title: '已選取的方塊:' + + 方塊。' + title: 已選取的方塊: material: - [material] remove_block_group: name: 移除方塊群組 - description: |- - 允許你移除 + description: '允許你移除 + 清單中的 - 方塊群組。 - title: '已選取的方塊群組:' + + 方塊群組。' + title: 已選取的方塊群組: material: - [material] material: name: [material] - description: '材料 ID:[id]' + description: 材料 ID:[id] selected: 已選取 block-group: name: [id] @@ -830,38 +887,40 @@ challenges: selected: 已選取 add_entity: name: 新增實體 - description: |- - 允許你新增 - 實體至清單。 + description: '允許你新增 + + 實體至清單。' add_entity_group: name: 新增實體群組 - description: |- - 允許你新增 - 實體群組至清單。 + description: '允許你新增 + + 實體群組至清單。' switch_entity: name: 切換顯示方式 - description: |- - 在生怪蛋 - 與生物頭顱之間切換。 + description: '在生怪蛋 + + 與生物頭顱之間切換。' remove_entity: name: 移除實體 - description: |- - 允許你移除 + description: '允許你移除 + 清單中的 - 實體。 - title: '已選取的實體:' + + 實體。' + title: 已選取的實體: entity: - [entity] remove_entity_group: name: 移除實體群組 - description: |- - 允許你移除 + description: '允許你移除 + 清單中的 - 實體群組。 - title: '已選取的實體群組:' + + 實體群組。' + title: 已選取的實體群組: entity: - [tag] entity: name: [entity] - description: '實體 ID:[id]' + description: 實體 ID:[id] selected: 已選取 entity-group: name: [id] @@ -869,41 +928,42 @@ challenges: selected: 已選取 inventory_type: name: 背包類型 - description: |- - 檢查玩家背包內 - 物品的挑戰。 + description: '檢查玩家背包內 + + 物品的挑戰。' island_type: name: 島嶼類型 - description: |- - 檢查玩家周圍 - 方塊或實體的挑戰。 + description: '檢查玩家周圍 + + 方塊或實體的挑戰。' other_type: name: 其他類型 - description: |- - 使用外掛或 + description: '使用外掛或 + 附加元件功能的挑戰, - 例如島嶼等級或金錢。 + + 例如島嶼等級或金錢。' statistic_type: name: 統計資料類型 - description: |- - 檢查玩家 - 統計資料的挑戰。 + description: '檢查玩家 + + 統計資料的挑戰。' save: name: 儲存 - description: |- - 儲存變更 - 並返回。 + description: '儲存變更 + + 並返回。' cancel: name: 取消 - description: |- - 捨棄變更 - 並返回。 + description: '捨棄變更 + + 並返回。' accept_selected: name: 確認選取 - description: |- - 確認所選項目, - 並重新開啟上一個選單。 - title: '已選取:' + description: '確認所選項目, + + 並重新開啟上一個選單。' + title: 已選取: element: - [element] advancement_element: name: [name] @@ -911,15 +971,15 @@ challenges: selected: 已選取 statistic_element: name: [statistic] - amount: '目標數值:[number]' + amount: 目標數值:[number] remove: - name: '扣除統計資料:[value]' + name: 扣除統計資料:[value] value: enabled: 已啟用 disabled: 已停用 - block: '目標方塊:[block]' - item: '目標物品:[item]' - entity: '目標實體:[entity]' + block: 目標方塊:[block] + item: 目標物品:[item] + entity: 目標實體:[entity] description: '[description]' selected: 已選取 environment_element: @@ -927,10 +987,41 @@ challenges: description: '[description]' search: name: 搜尋 - description: |- - 允許你輸入文字 - 搜尋指定項目。 - search: '搜尋值:[value]' + description: '允許你輸入文字 + + 搜尋指定項目。' + search: 搜尋值:[value] + biome: + description: 生態域 ID:[id] + name: [biome] + selected: 已選擇 + open_anywhere: + description: 允許玩家從任何地方開啟挑戰介面。\n若挑戰設有保護限制,完成挑戰\n仍需人在島嶼上。 + disabled: 已停用 + enabled: 已啟用 + name: 從任何地方開啟介面 + repeat_reward_island_level: + description: 可變更此挑戰重複完成時\n給予的島嶼等級獎勵。\n需要 Level 附加模組。 + name: 重複獎勵島嶼等級 + value: 目前數值:[number] + required_biomes: + description: 玩家必須站在其中一個\n指定的生態域內,才能完成\n此島嶼挑戰。 + list: ' - [biome]' + name: 所需生態域 + none: 不限生態域(任何生態域皆可)。 + title: 生態域: + reward_chance: + description: 完成挑戰時給予物品獎勵的\n機率百分比(1-100)。\n物品、金錢、經驗共用一次判定。\n指令獎勵永遠會執行。 + name: 獎勵機率 + value: 機率:[number]% + reward_island_level: + description: 可變更此挑戰給予的島嶼等級獎勵。\n需要 Level 附加模組。 + name: 獎勵島嶼等級 + value: 目前數值:[number] + toggle-undeployed: + hidden: 未部署的挑戰目前\n已隱藏。 + name: 未部署挑戰 + shown: 未部署的挑戰目前\n已顯示。 tips: click-to-select: 點擊 即可選取。 click-to-choose: 點擊 即可選擇。 @@ -970,157 +1061,167 @@ challenges: click-to-cancel: 點擊 即可取消。 click-to-save: 點擊 即可儲存。 click-to-deselect: 點擊 即可取消選取。 - click-on-item: |- - 請點擊 背包中的 - 物品。 + click-on-item: '請點擊 背包中的 + + 物品。' left-click-to-edit: 左鍵 即可編輯。 right-click-to-clear: 右鍵 即可清除。 click-to-previous: 點擊 即可查看上一頁。 click-to-next: 點擊 即可查看下一頁。 descriptions: - # This part generates description text for challenges object in all GUI's. challenge: - # The main part that generates description text. - # [description] comes from challenge.description - lore: |- - [description] + lore: '[description] + [status] + [cooldown] + [requirements] - [rewards] -# Team challenge lore line. [online] members online, [number] required, [size] team size. - team-requirement: '隊伍:[online] 人在線(需 [number] 人)' - # Shown instead of the above when the viewer has no team. + + [rewards]' + team-requirement: 隊伍:[online] 人在線(需 [number] 人) team-required: 需要加入隊伍才能完成 - # Contains a text generated inside [status] lore status: completed: 已完成 completed-times: 已完成 [number] 次 completed-times-of: 已完成 [number] / [max] 次 completed-times-reached: 已完成全部 [max] 次 - # Contains a text generated inside [cooldown] lore cooldown: - lore: |- - [timeout] - [wait-time] - timeout: '冷卻時間:[time]' - wait-time: '可再次完成時間:[time]' + lore: '[timeout] + + [wait-time]' + timeout: 冷卻時間:[time] + wait-time: 可再次完成時間:[time] in-days: '[number] 天 ' in-hours: '[number] 小時 ' in-minutes: '[number] 分 ' in-seconds: '[number] 秒' - # Contains a text generated inside [requirements] lore requirements: - lore: |- - [environment] + lore: '[environment] + [type-requirement] - [permissions] + + [permissions]' environment-single: 限定於 [environment] - environment-title: '限定維度:' + environment-title: 限定維度: environment-list: ' - [environment]' permission-single: 需要權限:[permission] - permissions-title: '需要以下權限:' + permissions-title: 需要以下權限: permissions-list: ' - [permission]' island: - lore: |- - [blocks] + lore: '[blocks] + [entities] + [search-radius] + [warning-block] - [warning-entity] - blocks-title: '需求方塊:' + + [warning-entity]' + blocks-title: 需求方塊: block-value: ' - [material]' blocks-value: ' - [number] x [material]' - entities-title: '需求實體:' + entities-title: 需求實體: entity-value: ' - [entity]' entities-value: ' - [number] x [entity]' search-radius: 距離玩家不得超過 [number] 格 warning-block: 完成後將移除方塊 warning-entity: 完成後將移除實體 + biome-value: ' - [biome]' + biomes-title: 所需生態域: inventory: - lore: |- - [items] - [warning] - item-title: '需求物品:' + lore: '[items] + + [warning]' + item-title: 需求物品: item-value: ' - [item]' items-value: ' - [number] x [item]' warning: 完成後將移除物品 other: - lore: |- - [experience] + lore: '[experience] + [experience-warning] + [money] + [money-warning] - [level] - experience: '需求經驗值:[number]' + + [level]' + experience: 需求經驗值:[number] experience-warning: 完成後將扣除經驗值 - money: '需求金額:[number]' + money: 需求金額:[number] money-warning: 完成後將扣除金額 - level: '需求島嶼等級:[number]' + level: 需求島嶼等級:[number] statistic: - lore: |- - [statistic] - [warning] - multiple-target: '[statistic]:[number] x [target]' - single-target: '[statistic]:[target]' - statistic: '[statistic]:[number]' + lore: '[statistic] + + [warning]' + multiple-target: [statistic]:[number] x [target] + single-target: [statistic]:[target] + statistic: [statistic]:[number] warning: 完成後將扣除統計資料 - # Contains a text generated inside [rewards] lore rewards: - lore: |- - 獎勵: + lore: '獎勵: + [text] + [items] + [experience] + [money] - [commands] - item-title: '物品:' + + [commands]' + item-title: 物品: item-value: ' - [item]' items-value: ' - [number] x [item]' - experience: '經驗值:[number]' - money: '金額:[number]' - commands-title: '指令:' + experience: 經驗值:[number] + money: 金額:[number] + commands-title: 指令: command: ' - [command]' - - # This part generates description text for levels object in all GUI's. level: - lore: |- - [text] + lore: '[text] + [status] + [waiver] - [rewards] + + [rewards]' status: completed: 已完成 completed-challenges-of: 已完成 [number] / [max] 項挑戰 locked: 已鎖定 - missing-challenges: |- - 還需要完成 + missing-challenges: '還需要完成 + [number] 項挑戰 - 才能解鎖此等級。 - waiver: |- - 可略過 [number] 項挑戰, - 即可解鎖下一個等級。 + + 才能解鎖此等級。' + waiver: '可略過 [number] 項挑戰, + + 即可解鎖下一個等級。' rewards: - lore: |- - 獎勵: + lore: '獎勵: + [text] + [items] + [experience] + [money] - [commands] - item-title: '物品:' + + [commands]' + item-title: 物品: item-value: ' - [item]' items-value: ' - [number] x [item]' - experience: '經驗值:[number]' - money: '金額:[number]' - commands-title: '指令:' + experience: 經驗值:[number] + money: 金額:[number] + commands-title: 指令: command: ' - [command]' - - # This part generates description for the Library Entry library: author: 作者:[author] version: 使用 Challenges [version] 製作 - lang: '語言:[lang]' + lang: 語言:[lang] gamemode: 主要適用於 [gamemode] conversations: prefix: '[BentoBox]: ' @@ -1143,35 +1244,37 @@ challenges: new-object-created: 已為 [gamemode] 建立新的物件。 object-already-exists: 物件 [id] 已存在,請選擇其他名稱。 invalid-challenge: 挑戰 [challenge] 包含無效資料,因此無法部署! - name-changed: '成功:名稱已更新。' + name-changed: 成功:名稱已更新。 write-description: 請在聊天室輸入新的描述。完成後請在新的一行輸入「quit」。 - description-changed: '成功:描述已更新。' + description-changed: 成功:描述已更新。 write-permissions: 請在聊天室逐行輸入所需權限。完成後請在新的一行輸入「quit」。 - permissions-changed: '成功:挑戰權限已更新。' + permissions-changed: 成功:挑戰權限已更新。 write-reward-text: 請在聊天室輸入新的獎勵文字。完成後請在新的一行輸入「quit」。 - reward-text-changed: '成功:獎勵文字已更新。' + reward-text-changed: 成功:獎勵文字已更新。 write-repeat-reward-text: 請在聊天室輸入新的重複獎勵文字。完成後請在新的一行輸入「quit」。 - repeat-reward-text-changed: '成功:重複獎勵文字已更新。' + repeat-reward-text-changed: 成功:重複獎勵文字已更新。 write-reward-commands: 請在聊天室逐行輸入新的獎勵指令。完成後請在新的一行輸入「quit」。 - reward-commands-changed: '成功:獎勵指令已更新。' + reward-commands-changed: 成功:獎勵指令已更新。 write-repeat-reward-commands: 請在聊天室逐行輸入新的重複獎勵指令。完成後請在新的一行輸入「quit」。 - repeat-reward-commands-changed: '成功:重複獎勵指令已更新。' + repeat-reward-commands-changed: 成功:重複獎勵指令已更新。 challenge-removed: [gamemode] 的挑戰 [challenge] 已從資料庫中移除。 confirm-challenge-deletion: 請確認是否要從資料庫中移除 [gamemode] 的挑戰 [challenge]。 level-removed: [gamemode] 的等級 [level] 已從資料庫中移除。 confirm-level-deletion: 請確認是否要從資料庫中移除 [gamemode] 的等級 [level]。 start-downloading: 開始下載並匯入挑戰圖書館。 - written-text: '輸入內容:' + written-text: 輸入內容: confirm-data-replacement: 請確認是否要以新的挑戰取代目前的挑戰資料。 - new-challenges-imported: '成功:[gamemode] 的新挑戰已匯入。' + new-challenges-imported: 成功:[gamemode] 的新挑戰已匯入。 exported-file-name: 請輸入匯出資料庫檔案的檔名。(輸入「cancel」即可取消) - database-export-completed: '成功:[world] 的資料庫已匯出完成,已產生檔案 [file]。' + database-export-completed: 成功:[world] 的資料庫已匯出完成,已產生檔案 [file]。 file-name-exist: 名為「[id]」的檔案已存在,無法覆寫。 write-search: 請輸入搜尋內容。(輸入「cancel」即可取消) search-updated: 搜尋內容已更新。 - enter-formula: |- - 請輸入公式,只能使用 PAPI Placeholder,以及 =、<、>、<=、>=、==、!=、AND、OR 等符號。 - 範例:%my_lifetime_count% >= 1000 AND %island_level% >= 100 + enter-formula: '請輸入公式,只能使用 PAPI Placeholder,以及 =、<、>、<=、>=、==、!=、AND、OR 等符號。 + + 範例:%my_lifetime_count% >= 1000 AND %island_level% >= 100' + confirm-instruction: 在聊天室輸入「confirm」以繼續,或輸入「cancel」以取消。 + input-repeat-count: 請在聊天室輸入重複次數。輸入 0 代表無限重複。 titles: challenge-title: 完成挑戰! challenge-subtitle: '[friendlyName]' @@ -1194,14 +1297,15 @@ challenges: name-has-completed-challenge: [name] 已完成 [value] 挑戰! name-has-completed-level: [name] 已完成 [value] 等級! load-skipping: '"[value]" 已存在,已略過。' - load-overwriting: '正在覆寫「[value]」' - load-add: '新增物件:[value]' + load-overwriting: 正在覆寫「[value]」 + load-add: 新增物件:[value] + no-reward-this-time: 運氣不太好——這次沒有獎勵! errors: no-name: 缺少挑戰名稱。 unknown-challenge: 未知的挑戰。 - not-valid-integer: |- - 輸入的整數「[value]」無效! - 必須介於 [min] 與 [max] 之間。 + not-valid-integer: '輸入的整數「[value]」無效! + + 必須介於 [min] 與 [max] 之間。' not-deployed: 此挑戰尚未部署! not-on-island: 你必須位於自己的島嶼上才能這麼做! challenge-level-not-available: 你尚未解鎖完成此挑戰所需的等級。 @@ -1215,9 +1319,9 @@ challenges: not-enough-money: 你的帳戶至少需要有 [value] 才能完成此挑戰。 not-enough-experience: 你至少需要 [value] 點經驗值才能完成此挑戰。 island-level: 你的島嶼至少需要達到等級 [number] 才能完成此挑戰! - no-load: '錯誤:無法載入 [file]。錯誤:[message]。' - load-error: '錯誤:無法載入 [value]。' - import-failed: '無法匯入挑戰:[message]。請查看伺服器主控台以取得詳細資訊。' + no-load: 錯誤:無法載入 [file]。錯誤:[message]。 + load-error: 錯誤:無法載入 [value]。 + import-failed: 無法匯入挑戰:[message]。請查看伺服器主控台以取得詳細資訊。 no-rank: 你的權限等級不足,無法執行此操作。 cannot-remove-items: 部分物品無法從你的背包中移除! exist-challenges-or-levels: 此世界已存在挑戰或等級,無法繼續! @@ -1236,104 +1340,22 @@ challenges: no-team: 這是一項隊伍挑戰,你必須加入隊伍才能完成! insufficient-team: 此隊伍挑戰需要至少 [number] 位隊伍成員在線,目前只有 [online] 位在線。 member-missing-share: [name] 尚未提供他應負責的份額([amount] x [item])。 -# # Showcase for manual material translation -# materials: -# # Names should be lowercase. -# cobblestone: "Cobblestone" -# # Also supports descriptions. -# stone: -# name: "Stone" -# description: "" -# item-stacks: -# # Non-specific item meta translations. -# # TYPE is the item type -# # META is a content of item meta. -# generic: "[type] [meta]" -# # Non-specific meta translations. Will replace [meta] -# meta: -# upgraded: "Upgraded" -# extended: "Extended" -# potion-meta: "[type] [upgraded] [extended]" -# # Be aware, enchants are always listed below item in separate line. -# enchant-meta: " - [type] [level]" -# skull-meta: ": [player-name]" -# book-meta: "[title] [author]" -# # Custom Enchantment Translation. -# enchant: -# menting: "Mending" -# unbreaking: "Unbreaking" -# # Custom Potion Translation. -# potion-type: -# water_breathing: "Water Breathing" -# # You can also create specific item translations -# # Like translate all potions. -# potion: -# # This will overwrite generic translation. -# name: "[type] [upgraded] [extended]" -# # Type is either specific translation or potion effect. -# uncraftable: "Uncraftable" -# water: "Water" -# mundane: "Mundane" -# thick: "Thick" -# awkward: "Awkward" -# night_vision: "Potion of Night Vision" -# invisibility: "Potion of Invisibility" -# jump: "Potion of Leaping" -# fire_resistance: "Potion of Fire Resistance" -# speed: "Potion of Swiftness" -# slowness: "Potion of Slowness" -# water_breathing: "Potion of Water Breathing" -# instant_heal: "Potion of Healing" -# instant_damage: "Potion of Harming" -# poison: "Potion of Poison" -# regen: "Potion of Regeneration" -# strength: "Potion of Strength" -# weakness: "Potion of Weakness" -# luck: "Potion of Luck" -# turtle_master: "Potion of Turtle Master" -# slow_falling: "Potion of Slow Falling" -# stone_shovel: -# # This will mean that only stone shovels will not show -# # meta information. -# name: "[type]" -# -# # Showcase how to support multi-linguistic challenges -# challenges: -# # Database ID name. -# example_challenge_id: -# name: "Translated Name" -# description: |- -# Translated Custom -# description -# reward-text: |- -# Translated Reward -# text -# repeat-reward-text: |- -# Translated Repeat -# Reward text -# levels: -# # Database ID name. -# example_level_id: -# name: "Translated Name" -# description: |- -# Translated Custom -# description -# reward-text: |- -# Translated Reward -# text + wrong-biome: 你必須站在 [biome] 生態域內才能完成此挑戰! protection: flags: CHALLENGES_ISLAND_PROTECTION: - description: |- - 設定哪些人 - 可以完成挑戰。 + description: '設定哪些人 + + 可以完成挑戰。' name: 挑戰保護 CHALLENGES_WORLD_PROTECTION: - description: |- - 啟用或停用 + description: '啟用或停用 + 玩家必須位於 + 自己的島嶼上 - 才能完成挑戰的限制。 + + 才能完成挑戰的限制。' name: 挑戰島嶼限制 hint: 島嶼外無法完成挑戰 version: 12 From 4a3b21108539943e50da044e14cd89fef37e4933 Mon Sep 17 00:00:00 2001 From: qwe664 <93234700+qwe664@users.noreply.github.com> Date: Mon, 10 Aug 2026 09:51:31 +0800 Subject: [PATCH 04/15] Update zh-TW.yml: complete translation coverage for v1.8.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Overview Completes the Traditional Chinese (zh-TW) translation coverage for Challenges v1.8.0. The existing translation was based on the v1.7.0 English source, so text introduced in v1.8.0 was not yet translated. ## What's added v1.8.0 introduced a biome requirement/selection feature. This PR adds the corresponding 39 keys (32 new entries plus a few fields appended to existing groups), covering: - `challenges.conversations.confirm-instruction` / `input-repeat-count` — conversation confirmation prompts - `challenges.errors.wrong-biome` — wrong biome error message - `challenges.gui.titles.biome-selector` — biome selector title - `challenges.gui.buttons.biome.*` — biome selection button - `challenges.gui.buttons.open_anywhere.*` — "open GUI anywhere" toggle - `challenges.gui.buttons.repeat_count.value-infinite` — infinite repeat count display (appended to the existing `repeat_count` group) - `challenges.gui.buttons.repeat_reward_island_level.*` / `reward_island_level.*` — island level reward settings - `challenges.gui.buttons.required_biomes.*` — required biomes list - `challenges.gui.buttons.reward_chance.*` — reward chance settings - `challenges.gui.buttons.toggle-undeployed.*` — undeployed challenges visibility toggle - `challenges.gui.descriptions.challenge.requirements.island.biomes-title` / `biome-value` — biome requirement descriptions (also added `[biomes]` to the `island.lore` placeholder list to match upstream) - `challenges.messages.no-reward-this-time` — no-reward message ## How this was done New content was inserted manually at the correct points in the existing file, without any automated reformatting or full re-serialization. As a result, this diff contains only additions — no existing translations, comments, or formatting were touched. ## Verification - Diffed the updated zh-TW.yml against the official en-US.yml (v1.8.0, 905 keys total) key-by-key. Confirmed 100% coverage with no missing or stray keys. - Validated YAML syntax and confirmed there are no duplicate keys. - New entries follow the existing translation's established terminology (e.g. consistent use of existing terms like "部署" for deploy, "島嶼等級" for island level, "重複次數" for repeat count). --- src/main/resources/locales/zh-TW.yml | 1251 +++++++++++++------------- 1 file changed, 645 insertions(+), 606 deletions(-) diff --git a/src/main/resources/locales/zh-TW.yml b/src/main/resources/locales/zh-TW.yml index 0dd6cac8..16c2d1ed 100644 --- a/src/main/resources/locales/zh-TW.yml +++ b/src/main/resources/locales/zh-TW.yml @@ -6,13 +6,15 @@ meta: authors: - BONNe + challenges: materials: - any: 任何 + any: '任何' all_hanging_signs: name: 任何懸掛式告示牌 all_signs: name: 任何告示牌 + commands: admin: main: @@ -42,9 +44,13 @@ challenges: parameters: [count] gui: titles: + # The title for the Main GUI player-gui: 挑戰選單 + # The title for the Main GUI gamemode-gui: 選擇遊戲模式 + # The title for the Multiple Completion GUI multiple-gui: 要完成幾次? + # GUI titles below are visible just for Admins. admin-gui: 挑戰管理選單 edit-challenge: 編輯 [challenge] edit-level: 編輯 [level] @@ -69,121 +75,129 @@ challenges: environment-selector: 維度選擇器 biome-selector: 生態域選擇器 buttons: + # Button in the Challenges GUI that allows to select free challenges. free-challenges: name: 自由挑戰 - description: '顯示所有 - - 自由挑戰' + description: |- + 顯示所有 + 自由挑戰 +# Button that is used to return to previous GUI or exit it completely. return: name: 返回 - description: '返回上一個選單 - - 或離開選單' + description: |- + 返回上一個選單 + 或離開選單 +# Button that is used in multi-page GUIs which allows to return to previous page. previous: name: 上一頁 description: 切換至第 [number] 頁 +# Button that is used in multi-page GUIs which allows to go to next page. next: name: 下一頁 description: 切換至第 [number] 頁 +# Button that allows to reduce number reduce: name: 減少 description: 減少 [number] +# Button that allows to increase number increase: name: 增加 description: 增加 [number] +# Button that displays and allows completing challenge accept: name: 完成 - description: '完成挑戰 - - [number] 次' + description: |- + 完成挑戰 + [number] 次 +# Button that allows to quit the current gui. quit: name: 離開 description: 離開選單。 +# All following buttons are mainly for Admin GUI. complete_user_challenges: name: 完成玩家挑戰 - description: '選擇一位玩家, - - 並替其完成挑戰。' + description: |- + 選擇一位玩家, + 並替其完成挑戰。 reset_user_challenges: name: 重設玩家挑戰 - description: '選擇一位玩家, - - 並重設其挑戰。' + description: |- + 選擇一位玩家, + 並重設其挑戰。 add_challenge: name: 建立挑戰 - description: '開始建立 - - 新的挑戰。' + description: |- + 開始建立 + 新的挑戰。 add_level: name: 建立等級 - description: '開始建立 - - 新的等級。' + description: |- + 開始建立 + 新的等級。 edit_challenge: name: 編輯挑戰 - description: '選擇並編輯 - - 一項挑戰。' + description: |- + 選擇並編輯 + 一項挑戰。 edit_level: name: 編輯等級 - description: '選擇並編輯 - - 一個等級。' + description: |- + 選擇並編輯 + 一個等級。 delete_challenge: name: 刪除挑戰 - description: '選擇並刪除 - - 一項挑戰。' + description: |- + 選擇並刪除 + 一項挑戰。 delete_level: name: 刪除等級 - description: '選擇並刪除 - - 一個等級。' + description: |- + 選擇並刪除 + 一個等級。 edit_settings: name: 設定 - description: '檢視並編輯 - - 附加元件設定。' + description: |- + 檢視並編輯 + 附加元件設定。 complete_wipe: name: 完全清除 - description: '完整清除挑戰 - + description: |- + 完整清除挑戰 附加元件資料庫, - - 包含所有玩家資料。' + 包含所有玩家資料。 challenge_wipe: name: 清除挑戰資料 - description: '完整清除資料庫中的 - - 所有挑戰與等級。' + description: |- + 完整清除資料庫中的 + 所有挑戰與等級。 user_wipe: name: 清除玩家資料 - description: '完整清除資料庫中的 - - 所有玩家資料。' + description: |- + 完整清除資料庫中的 + 所有玩家資料。 library: name: 圖書館 - description: '開啟公開的 - - 挑戰圖書館。' - downloading: '已提出下載 - - 圖書館請求……' + description: |- + 開啟公開的 + 挑戰圖書館。 + downloading: |- + 已提出下載 + 圖書館請求…… import_database: name: 匯入資料庫 - description: '匯入已匯出的 - - 挑戰資料庫。' + description: |- + 匯入已匯出的 + 挑戰資料庫。 import_template: name: 匯入範本 - description: '匯入包含挑戰的 - - 範本檔案。' + description: |- + 匯入包含挑戰的 + 範本檔案。 export_challenges: name: 匯出挑戰 - description: '將資料庫匯出至 - - 本機檔案。' + description: |- + 將資料庫匯出至 + 本機檔案。 properties: name: 屬性 description: 檢視所有主要屬性。 @@ -195,324 +209,291 @@ challenges: description: 檢視獎勵屬性。 hide_reward_items: name: 隱藏獎勵物品 - description: '切換是否在選單中 - - 顯示獎勵物品。' + description: |- + 切換是否在選單中 + 顯示獎勵物品。 hide: 隱藏 show: 顯示 deployed: name: 部署 - description: '切換此挑戰是否已部署, - + description: |- + 切換此挑戰是否已部署, 並允許玩家 - - 完成。' + 完成。 enabled: 已啟用 disabled: 已停用 name: name: 名稱 - description: '允許你變更 - - 顯示名稱。' - value: 目前:[name] + description: |- + 允許你變更 + 顯示名稱。 + value: '目前:[name]' remove_on_complete: name: 完成後隱藏 - description: '切換玩家完成挑戰後, - + description: |- + 切換玩家完成挑戰後, 是否將此挑戰 - - 隱藏。' + 隱藏。 enabled: 已啟用 disabled: 已停用 team_challenge: name: 團隊挑戰 - description: '切換此挑戰是否為團隊挑戰。 - + description: |- + 切換此挑戰是否為團隊挑戰。 團隊挑戰需要有隊伍, - - 並於整座島嶼共用完成狀態與冷卻時間。' + 並於整座島嶼共用完成狀態與冷卻時間。 enabled: 已啟用 disabled: 已停用 team_presence: name: 團隊在線率 - description: '完成此挑戰時, - + description: |- + 完成此挑戰時, 隊伍中必須在線的 - 成員百分比。 - - 設為 0 可停用此限制。' - value: 目前:[number]% + 設為 0 可停用此限制。 + value: '目前:[number]%' aggregate_team: name: 團隊合併計算 - description: '將所有在線成員的 - + description: |- + 將所有在線成員的 需求物品/統計資料合併計算 - - (共同貢獻、共同努力)。' + (共同貢獻、共同努力)。 enabled: 已啟用 disabled: 已停用 per_member: name: 每位成員皆需貢獻 - description: '每位在線成員都必須繳交 - + description: |- + 每位在線成員都必須繳交 自己的份額(需求數量為 - - 團隊總需求,平均分配給在線成員)。' + 團隊總需求,平均分配給在線成員)。 enabled: 已啟用 disabled: 已停用 hide_if_no_team: name: 無隊伍時隱藏 - description: '啟用後,沒有隊伍的玩家 - + description: |- + 啟用後,沒有隊伍的玩家 將完全看不到此挑戰。 - - 停用後則仍會顯示,但無法完成。' + 停用後則仍會顯示,但無法完成。 enabled: 已啟用 disabled: 已停用 description: name: 描述 - description: '設定此挑戰的描述。 - - 需自行加入色彩代碼。' - value: 目前描述: + description: |- + 設定此挑戰的描述。 + 需自行加入色彩代碼。 + value: '目前描述:' environment: name: 維度 - description: '允許你將此挑戰 - - 限制於指定維度。' + description: |- + 允許你將此挑戰 + 限制於指定維度。 enabled: disabled: order: name: 排序 - description: '允許你調整 - + description: |- + 允許你調整 物件的排序順序。 - 若排序值相同, - 則依照其 - - 唯一 ID 名稱排序。' - value: 目前排序:[number] + 唯一 ID 名稱排序。 + value: '目前排序:[number]' icon: name: 圖示 - description: '允許你變更 - - 此挑戰的圖示。' + description: |- + 允許你變更 + 此挑戰的圖示。 locked_icon: name: 鎖定圖示 - description: '允許你變更 - - 鎖定狀態的等級圖示。' + description: |- + 允許你變更 + 鎖定狀態的等級圖示。 required_permissions: name: 需求權限 - description: '允許你修改 - + description: |- + 允許你修改 完成此挑戰 - - 所需的權限。' - title: 權限: + 所需的權限。 + title: '權限:' permission: ' - [permission]' none: 尚未設定任何權限。 remove_entities: name: 移除實體 - description: '切換完成挑戰後, - + description: |- + 切換完成挑戰後, 是否將所需實體 - - 自世界中移除。' + 自世界中移除。 enabled: 已啟用 disabled: 已停用 required_entities: name: 需求實體 - description: '允許你修改 - + description: |- + 允許你修改 完成此挑戰 - - 所需的實體。' - title: 實體: + 所需的實體。 + title: '實體:' list: ' - [number] x [entity]' none: 尚未新增任何實體。 remove_blocks: name: 移除方塊 - description: '切換完成挑戰後, - + description: |- + 切換完成挑戰後, 是否將所需方塊 - - 自世界中移除。' + 自世界中移除。 enabled: 已啟用 disabled: 已停用 required_blocks: name: 需求方塊 - description: '允許你修改 - + description: |- + 允許你修改 完成此挑戰 - - 所需的方塊。' - title: 方塊: + 所需的方塊。 + title: '方塊:' list: ' - [number] x [block]' none: 尚未新增任何方塊。 required_statistics: name: 需求統計資料 - description: '允許你修改 - + description: |- + 允許你修改 完成此挑戰 - - 所需的統計資料。' - title: 統計資料: + 所需的統計資料。 + title: '統計資料:' list: ' - [name]' none: 尚未新增任何統計資料。 required_advancements: name: 需求進度 - description: '允許你修改 - + description: |- + 允許你修改 完成此挑戰 - - 所需的進度。' - title: 進度: + 所需的進度。 + title: '進度:' list: ' - [name]' none: 尚未新增任何進度。 search_radius: name: 搜尋半徑 - description: '允許你修改 - + description: |- + 允許你修改 以玩家為中心偵測 - - 方塊及/或實體的半徑。' - value: 目前距離:[number] + 方塊及/或實體的半徑。 + value: '目前距離:[number]' remove_items: name: 移除物品 - description: '切換完成挑戰後, - + description: |- + 切換完成挑戰後, 是否從玩家背包中 - - 移除所需物品。' + 移除所需物品。 enabled: 已啟用 disabled: 已停用 required_items: name: 需求物品 - description: '允許你修改 - + description: |- + 允許你修改 完成此挑戰 - - 所需的物品。' - title: 物品: + 所需的物品。 + title: '物品:' list: ' - [number] x [item]' none: 尚未新增任何物品。 add_ignored_meta: name: 新增忽略中繼資料 - description: '允許你指定哪些物品 - + description: |- + 允許你指定哪些物品 應忽略其 - - 中繼資料。' - title: 物品: + 中繼資料。 + title: '物品:' list: ' - [number] x [item]' none: 尚未新增任何物品。 remove_ignored_meta: name: 移除忽略中繼資料 - description: '移除會忽略 - - 中繼資料的物品。' + description: |- + 移除會忽略 + 中繼資料的物品。 remove_experience: name: 移除經驗值 - description: '切換完成挑戰後, - + description: |- + 切換完成挑戰後, 是否扣除玩家 - - 所需的經驗值。' + 所需的經驗值。 enabled: 已啟用 disabled: 已停用 required_experience: name: 需求經驗值 - description: '允許你修改 - + description: |- + 允許你修改 玩家所需的 - - 經驗值。' - value: 目前經驗值:[number] + 經驗值。 + value: '目前經驗值:[number]' required_level: name: 需求島嶼等級 - description: '允許你修改 - + description: |- + 允許你修改 完成此挑戰 - - 所需的島嶼等級。' - value: 目前等級:[number] + 所需的島嶼等級。 + value: '目前等級:[number]' required_materialtags: name: 需求方塊群組 - description: '允許你修改 - + description: |- + 允許你修改 完成此挑戰 - - 所需的方塊群組。' - title: 方塊群組: + 所需的方塊群組。 + title: '方塊群組:' list: ' - [number] x [tag]' none: 尚未新增任何方塊群組。 required_entitytags: name: 需求實體群組 - description: '允許你修改 - + description: |- + 允許你修改 完成此挑戰 - - 所需的實體群組。' - title: 實體群組: + 所需的實體群組。 + title: '實體群組:' list: ' - [number] x [tag]' none: 尚未新增任何實體群組。 remove_money: name: 扣除金錢 - description: '切換完成挑戰後, - + description: |- + 切換完成挑戰後, 是否從玩家帳戶 - - 扣除所需金額。' + 扣除所需金額。 enabled: 已啟用 disabled: 已停用 required_money: name: 需求金額 - description: '允許你修改 - + description: |- + 允許你修改 完成挑戰所需的 - - 玩家帳戶金額。' - value: 目前數值:[number] + 玩家帳戶金額。 + value: '目前數值:[number]' required_papi: name: 需求 PAPI - description: '檢查一個可包含 - + description: |- + 檢查一個可包含 PAPI Placeholder - - 以及數學、邏輯運算的公式。' - value: 公式:[formula] + 以及數學、邏輯運算的公式。 + value: '公式:[formula]' statistic: name: 統計資料 - description: '允許你修改 - + description: |- + 允許你修改 此挑戰所檢查的 - - 統計資料類型。' - value: 目前數值:[statistic] + 統計資料類型。 + value: '目前數值:[statistic]' statistic_amount: name: 目標數值 - description: '允許你修改 - + description: |- + 允許你修改 必須達成的 - - 統計資料目標值。' - value: 目前數值:[number] + 統計資料目標值。 + value: '目前數值:[number]' add_statistic: name: 新增統計資料 - description: '允許你新增 - - 統計資料至清單。' + description: |- + 允許你新增 + 統計資料至清單。 remove_statistic: name: 移除統計資料 - description: '允許你移除 - + description: |- + 允許你移除 清單中的 - - 統計資料。' + 統計資料。 enabled: 已啟用 disabled: 已停用 advancement: @@ -520,132 +501,113 @@ challenges: description: '[description]' add_advancement: name: 新增進度 - description: '允許你新增 - - 進度至清單。' + description: |- + 允許你新增 + 進度至清單。 remove_advancement: name: 移除進度 - description: '允許你移除 - + description: |- + 允許你移除 清單中的 - - 進度。' + 進度。 enabled: 已啟用 disabled: 已停用 statistic_blocks: name: 目標方塊 - description: '允許你修改 - + description: |- + 允許你修改 統計資料的 - - 目標方塊。' - value: 目前方塊:[block] + 目標方塊。 + value: '目前方塊:[block]' statistic_items: name: 目標物品 - description: '允許你修改 - + description: |- + 允許你修改 統計資料的 - - 目標物品。' - value: 目前物品:[item] + 目標物品。 + value: '目前物品:[item]' statistic_entities: name: 目標實體 - description: '允許你修改 - + description: |- + 允許你修改 統計資料的 - - 目標實體。' - value: 目前實體:[entity] + 目標實體。 + value: '目前實體:[entity]' reward_text: name: 獎勵文字 - description: '設定獎勵文字。 - - 需自行加入色彩代碼。' - value: 目前文字: + description: |- + 設定獎勵文字。 + 需自行加入色彩代碼。 + value: '目前文字:' repeat_reward_text: name: 重複獎勵文字 - description: '設定此挑戰的 - + description: |- + 設定此挑戰的 重複獎勵文字。 - - 需自行加入色彩代碼。' - value: 目前文字: + 需自行加入色彩代碼。 + value: '目前文字:' reward_items: name: 獎勵物品 description: 允許你修改獎勵物品。 - title: 物品: + title: '物品:' list: ' - [number] x [item]' none: 尚未新增任何物品。 repeat_reward_items: name: 重複獎勵物品 - description: '允許你修改 - - 此挑戰的重複獎勵物品。' - title: 物品: + description: |- + 允許你修改 + 此挑戰的重複獎勵物品。 + title: '物品:' list: ' - [number] x [item]' none: 尚未新增任何物品。 reward_experience: name: 獎勵經驗值 - description: '允許你修改 - - 玩家獲得的獎勵經驗值。' - value: 獎勵經驗值:[number] + description: |- + 允許你修改 + 玩家獲得的獎勵經驗值。 + value: '獎勵經驗值:[number]' repeat_reward_experience: name: 重複獎勵經驗值 - description: '允許你修改 - - 玩家獲得的重複獎勵經驗值。' - value: 獎勵經驗值:[number] + description: |- + 允許你修改 + 玩家獲得的重複獎勵經驗值。 + value: '獎勵經驗值:[number]' reward_money: name: 獎勵金額 description: 允許你修改獎勵金額。 - value: 目前數值:[number] + value: '目前數值:[number]' repeat_reward_money: name: 重複獎勵金額 - description: '允許你修改 - - 此挑戰的重複獎勵金額。' - value: 目前數值:[number] + description: |- + 允許你修改 + 此挑戰的重複獎勵金額。 + value: '目前數值:[number]' reward_commands: name: 獎勵指令 - description: '設定獎勵指令。 - + description: |- + 設定獎勵指令。 提示: - 指令前不需要加上「/」, - 系統會自動補上。 - 預設會由伺服器執行指令。 - 若在開頭加入 [SELF], - 則改由玩家自行執行。 - 也支援 [player] Placeholder, - - 會自動替換為完成挑戰的玩家名稱。' - value: 目前指令: + 會自動替換為完成挑戰的玩家名稱。 + value: '目前指令:' repeat_reward_commands: name: 重複獎勵指令 - description: '設定此挑戰的重複獎勵指令。 - + description: |- + 設定此挑戰的重複獎勵指令。 提示: - 指令前不需要加上「/」, - 系統會自動補上。 - 預設會由伺服器執行指令。 - 若在開頭加入 [SELF], - 則改由玩家自行執行。 - 也支援 [player] Placeholder, - - 會自動替換為完成挑戰的玩家名稱。' - value: 目前指令: + 會自動替換為完成挑戰的玩家名稱。 + value: '目前指令:' repeatable: name: 可重複完成 description: 切換此挑戰是否可重複完成。 @@ -653,153 +615,138 @@ challenges: disabled: 已停用 repeat_count: name: 重複次數 - description: '允許你修改 - - 此挑戰可重複完成的次數。' - value: 目前數值:[number] - value-infinite: 目前數值:[number] (無限) + description: |- + 允許你修改 + 此挑戰可重複完成的次數。 + value: '目前數值:[number]' + value-infinite: '目前數值:[number] (無限)' cool_down: name: 冷卻時間 - description: '允許你修改 - + description: |- + 允許你修改 可重複完成挑戰之間 - - 所需等待的時間(秒)。' - value: 目前數值:[time] + 所需等待的時間(秒)。 + value: '目前數值:[time]' challenges: name: 挑戰 - description: '檢視指派至 - - 此等級的挑戰。' + description: |- + 檢視指派至 + 此等級的挑戰。 waiver_amount: name: 可略過數量 - description: '允許你設定可未完成 - + description: |- + 允許你設定可未完成 多少項挑戰即可解鎖 - - 下一個等級。' - value: 目前數值:[number] + 下一個等級。 + value: '目前數值:[number]' add_challenges: name: 新增挑戰 - description: '允許你選擇並新增 - - 挑戰至此等級。' + description: |- + 允許你選擇並新增 + 挑戰至此等級。 remove_challenges: name: 移除挑戰 - description: '允許你選擇並移除 - - 此等級中的挑戰。' + description: |- + 允許你選擇並移除 + 此等級中的挑戰。 reset_on_new: name: 建立新島時重設 - description: '切換玩家離開島嶼 - + description: |- + 切換玩家離開島嶼 或建立新島時, - - 是否重設挑戰。' + 是否重設挑戰。 enabled: 已啟用 disabled: 已停用 broadcast: name: 廣播 - description: '首次完成挑戰或等級時, - - 向所有玩家廣播。' + description: |- + 首次完成挑戰或等級時, + 向所有玩家廣播。 enabled: 已啟用 disabled: 已停用 remove_completed: name: 隱藏已完成項目 - description: '將已完成的挑戰 - - 從選單中隱藏。' + description: |- + 將已完成的挑戰 + 從選單中隱藏。 enabled: 已啟用 disabled: 已停用 glow_completed: name: 已完成挑戰發光 - description: '為已完成的挑戰 - - 套用附魔發光效果。' + description: |- + 為已完成的挑戰 + 套用附魔發光效果。 enabled: 已啟用 disabled: 已停用 glow_completed_levels: name: 已完成等級發光 - description: '為已完成的等級 - - 套用附魔發光效果。' + description: |- + 為已完成的等級 + 套用附魔發光效果。 enabled: 已啟用 disabled: 已停用 store_history: name: 儲存歷史紀錄 - description: '每次完成挑戰時 - + description: |- + 每次完成挑戰時 儲存內部歷史紀錄。 - 目前僅能於 - - 資料庫中檢視。' + 資料庫中檢視。 enabled: 已啟用 disabled: 已停用 data_per_island: name: 依島嶼儲存 - description: '依照島嶼儲存 - + description: |- + 依照島嶼儲存 已完成的挑戰。 - 進度會與所有 - - 隊伍成員共享。' + 隊伍成員共享。 enabled: 已啟用 disabled: 已停用 show_title: name: 顯示標題 - description: '完成挑戰或等級時 - - 顯示標題。' + description: |- + 完成挑戰或等級時 + 顯示標題。 enabled: 已啟用 disabled: 已停用 gamemode_gui: name: 遊戲模式選擇選單 - description: '啟用可透過 - + description: |- + 啟用可透過 /challenges 指令開啟的 - 單一選單。 - - (需重新啟動伺服器)' + (需重新啟動伺服器) enabled: 已啟用 disabled: 已停用 locked_level_icon: name: 預設鎖定等級圖示 - description: '所有鎖定等級的預設圖示。 - - 每個等級皆可個別覆寫。' + description: |- + 所有鎖定等級的預設圖示。 + 每個等級皆可個別覆寫。 purge_history: name: 歷史紀錄保存天數 - description: '設定玩家資料中 - + description: |- + 設定玩家資料中 歷史紀錄的保存天數。 - 設為 0 表示 - - 永不刪除。' - value: 目前數值:[number] + 永不刪除。 + value: '目前數值:[number]' title_showtime: name: 標題顯示時間 - description: '設定標題 - + description: |- + 設定標題 顯示給玩家的 - - Tick 數。' - value: 目前數值:[number] + Tick 數。 + value: '目前數值:[number]' active_world_list: name: 僅顯示目前世界 - description: '若已啟用遊戲模式選擇選單, - + description: |- + 若已啟用遊戲模式選擇選單, 此設定決定選單 - 要顯示遊戲模式選擇, - 還是目前世界的挑戰。 - - (需重新啟動伺服器)' + (需重新啟動伺服器) enabled: 已啟用 disabled: 已停用 visibility_mode: @@ -812,38 +759,38 @@ challenges: toggleable: 允許切換 include_undeployed: name: 包含未部署挑戰 - description: '設定未部署的挑戰 - - 是否納入等級完成度計算。' + description: |- + 設定未部署的挑戰 + 是否納入等級完成度計算。 enabled: 已啟用 disabled: 已停用 download: name: 下載圖書館 - description: '手動更新可用的 - - 挑戰圖書館。' + description: |- + 手動更新可用的 + 挑戰圖書館。 enabled: 清除快取 disabled: 保留快取 language: name: 語言 - description: '依語言篩選 - - 挑戰圖書館。' - current: 目前顯示:[lang] + description: |- + 依語言篩選 + 挑戰圖書館。 + current: '目前顯示:[lang]' all: 全部 player: name: [name] - description: 島主:[owner] - members: 島嶼成員: + description: '島主:[owner]' + members: '島嶼成員:' member: - [name] - no-island: '此玩家 - - 沒有島嶼。' + no-island: |- + 此玩家 + 沒有島嶼。 player_list: name: 選擇玩家清單 - description: '選擇要顯示的 - - 玩家清單。' + description: |- + 選擇要顯示的 + 玩家清單。 enabled: disabled: online: 在線玩家 @@ -851,35 +798,33 @@ challenges: in_world: 世界中的玩家 add_block: name: 新增方塊 - description: '允許你新增 - - 方塊至清單。' + description: |- + 允許你新增 + 方塊至清單。 add_block_group: name: 新增方塊群組 - description: '允許你新增 - - 方塊群組至清單。' + description: |- + 允許你新增 + 方塊群組至清單。 remove_block: name: 移除方塊 - description: '允許你移除 - + description: |- + 允許你移除 清單中的 - - 方塊。' - title: 已選取的方塊: + 方塊。 + title: '已選取的方塊:' material: - [material] remove_block_group: name: 移除方塊群組 - description: '允許你移除 - + description: |- + 允許你移除 清單中的 - - 方塊群組。' - title: 已選取的方塊群組: + 方塊群組。 + title: '已選取的方塊群組:' material: - [material] material: name: [material] - description: 材料 ID:[id] + description: '材料 ID:[id]' selected: 已選取 block-group: name: [id] @@ -887,40 +832,38 @@ challenges: selected: 已選取 add_entity: name: 新增實體 - description: '允許你新增 - - 實體至清單。' + description: |- + 允許你新增 + 實體至清單。 add_entity_group: name: 新增實體群組 - description: '允許你新增 - - 實體群組至清單。' + description: |- + 允許你新增 + 實體群組至清單。 switch_entity: name: 切換顯示方式 - description: '在生怪蛋 - - 與生物頭顱之間切換。' + description: |- + 在生怪蛋 + 與生物頭顱之間切換。 remove_entity: name: 移除實體 - description: '允許你移除 - + description: |- + 允許你移除 清單中的 - - 實體。' - title: 已選取的實體: + 實體。 + title: '已選取的實體:' entity: - [entity] remove_entity_group: name: 移除實體群組 - description: '允許你移除 - + description: |- + 允許你移除 清單中的 - - 實體群組。' - title: 已選取的實體群組: + 實體群組。 + title: '已選取的實體群組:' entity: - [tag] entity: name: [entity] - description: 實體 ID:[id] + description: '實體 ID:[id]' selected: 已選取 entity-group: name: [id] @@ -928,42 +871,41 @@ challenges: selected: 已選取 inventory_type: name: 背包類型 - description: '檢查玩家背包內 - - 物品的挑戰。' + description: |- + 檢查玩家背包內 + 物品的挑戰。 island_type: name: 島嶼類型 - description: '檢查玩家周圍 - - 方塊或實體的挑戰。' + description: |- + 檢查玩家周圍 + 方塊或實體的挑戰。 other_type: name: 其他類型 - description: '使用外掛或 - + description: |- + 使用外掛或 附加元件功能的挑戰, - - 例如島嶼等級或金錢。' + 例如島嶼等級或金錢。 statistic_type: name: 統計資料類型 - description: '檢查玩家 - - 統計資料的挑戰。' + description: |- + 檢查玩家 + 統計資料的挑戰。 save: name: 儲存 - description: '儲存變更 - - 並返回。' + description: |- + 儲存變更 + 並返回。 cancel: name: 取消 - description: '捨棄變更 - - 並返回。' + description: |- + 捨棄變更 + 並返回。 accept_selected: name: 確認選取 - description: '確認所選項目, - - 並重新開啟上一個選單。' - title: 已選取: + description: |- + 確認所選項目, + 並重新開啟上一個選單。 + title: '已選取:' element: - [element] advancement_element: name: [name] @@ -971,15 +913,15 @@ challenges: selected: 已選取 statistic_element: name: [statistic] - amount: 目標數值:[number] + amount: '目標數值:[number]' remove: - name: 扣除統計資料:[value] + name: '扣除統計資料:[value]' value: enabled: 已啟用 disabled: 已停用 - block: 目標方塊:[block] - item: 目標物品:[item] - entity: 目標實體:[entity] + block: '目標方塊:[block]' + item: '目標物品:[item]' + entity: '目標實體:[entity]' description: '[description]' selected: 已選取 environment_element: @@ -987,41 +929,62 @@ challenges: description: '[description]' search: name: 搜尋 - description: '允許你輸入文字 - - 搜尋指定項目。' - search: 搜尋值:[value] - biome: - description: 生態域 ID:[id] - name: [biome] - selected: 已選擇 - open_anywhere: - description: 允許玩家從任何地方開啟挑戰介面。\n若挑戰設有保護限制,完成挑戰\n仍需人在島嶼上。 - disabled: 已停用 - enabled: 已啟用 - name: 從任何地方開啟介面 - repeat_reward_island_level: - description: 可變更此挑戰重複完成時\n給予的島嶼等級獎勵。\n需要 Level 附加模組。 - name: 重複獎勵島嶼等級 - value: 目前數值:[number] + description: |- + 允許你輸入文字 + 搜尋指定項目。 + search: '搜尋值:[value]' + # Button shown only when undeployed-view-mode is TOGGLEABLE. It lets each player + # show or hide the challenges that are not yet deployed. + toggle-undeployed: + name: 未部署挑戰 + shown: |- + 未部署的挑戰目前 + 已顯示。 + hidden: |- + 未部署的挑戰目前 + 已隱藏。 required_biomes: - description: 玩家必須站在其中一個\n指定的生態域內,才能完成\n此島嶼挑戰。 - list: ' - [biome]' name: 所需生態域 + description: |- + 玩家必須站在其中一個 + 指定的生態域內,才能完成 + 此島嶼挑戰。 + title: '生態域:' + list: ' - [biome]' none: 不限生態域(任何生態域皆可)。 - title: 生態域: reward_chance: - description: 完成挑戰時給予物品獎勵的\n機率百分比(1-100)。\n物品、金錢、經驗共用一次判定。\n指令獎勵永遠會執行。 name: 獎勵機率 - value: 機率:[number]% + description: |- + 完成挑戰時給予物品獎勵的 + 機率百分比(1-100)。 + 物品、金錢、經驗共用一次判定。 + 指令獎勵永遠會執行。 + value: '機率:[number]%' reward_island_level: - description: 可變更此挑戰給予的島嶼等級獎勵。\n需要 Level 附加模組。 name: 獎勵島嶼等級 - value: 目前數值:[number] - toggle-undeployed: - hidden: 未部署的挑戰目前\n已隱藏。 - name: 未部署挑戰 - shown: 未部署的挑戰目前\n已顯示。 + description: |- + 可變更此挑戰給予的島嶼等級獎勵。 + 需要 Level 附加模組。 + value: '目前數值:[number]' + repeat_reward_island_level: + name: 重複獎勵島嶼等級 + description: |- + 可變更此挑戰重複完成時 + 給予的島嶼等級獎勵。 + 需要 Level 附加模組。 + value: '目前數值:[number]' + open_anywhere: + name: 從任何地方開啟介面 + description: |- + 允許玩家從任何地方開啟挑戰介面。 + 若挑戰設有保護限制,完成挑戰 + 仍需人在島嶼上。 + enabled: 已啟用 + disabled: 已停用 + biome: + name: [biome] + description: '生態域 ID:[id]' + selected: 已選擇 tips: click-to-select: 點擊 即可選取。 click-to-choose: 點擊 即可選擇。 @@ -1061,167 +1024,160 @@ challenges: click-to-cancel: 點擊 即可取消。 click-to-save: 點擊 即可儲存。 click-to-deselect: 點擊 即可取消選取。 - click-on-item: '請點擊 背包中的 - - 物品。' + click-on-item: |- + 請點擊 背包中的 + 物品。 left-click-to-edit: 左鍵 即可編輯。 right-click-to-clear: 右鍵 即可清除。 click-to-previous: 點擊 即可查看上一頁。 click-to-next: 點擊 即可查看下一頁。 descriptions: + # This part generates description text for challenges object in all GUI's. challenge: - lore: '[description] - + # The main part that generates description text. + # [description] comes from challenge.description + lore: |- + [description] [status] - [cooldown] - [requirements] - - [rewards]' - team-requirement: 隊伍:[online] 人在線(需 [number] 人) + [rewards] +# Team challenge lore line. [online] members online, [number] required, [size] team size. + team-requirement: '隊伍:[online] 人在線(需 [number] 人)' + # Shown instead of the above when the viewer has no team. team-required: 需要加入隊伍才能完成 + # Contains a text generated inside [status] lore status: completed: 已完成 completed-times: 已完成 [number] 次 completed-times-of: 已完成 [number] / [max] 次 completed-times-reached: 已完成全部 [max] 次 + # Contains a text generated inside [cooldown] lore cooldown: - lore: '[timeout] - - [wait-time]' - timeout: 冷卻時間:[time] - wait-time: 可再次完成時間:[time] + lore: |- + [timeout] + [wait-time] + timeout: '冷卻時間:[time]' + wait-time: '可再次完成時間:[time]' in-days: '[number] 天 ' in-hours: '[number] 小時 ' in-minutes: '[number] 分 ' in-seconds: '[number] 秒' + # Contains a text generated inside [requirements] lore requirements: - lore: '[environment] - + lore: |- + [environment] [type-requirement] - - [permissions]' + [permissions] environment-single: 限定於 [environment] - environment-title: 限定維度: + environment-title: '限定維度:' environment-list: ' - [environment]' permission-single: 需要權限:[permission] - permissions-title: 需要以下權限: + permissions-title: '需要以下權限:' permissions-list: ' - [permission]' island: - lore: '[blocks] - + lore: |- + [blocks] [entities] - + [biomes] [search-radius] - [warning-block] - - [warning-entity]' - blocks-title: 需求方塊: + [warning-entity] + biomes-title: '所需生態域:' + biome-value: ' - [biome]' + blocks-title: '需求方塊:' block-value: ' - [material]' blocks-value: ' - [number] x [material]' - entities-title: 需求實體: + entities-title: '需求實體:' entity-value: ' - [entity]' entities-value: ' - [number] x [entity]' search-radius: 距離玩家不得超過 [number] 格 warning-block: 完成後將移除方塊 warning-entity: 完成後將移除實體 - biome-value: ' - [biome]' - biomes-title: 所需生態域: inventory: - lore: '[items] - - [warning]' - item-title: 需求物品: + lore: |- + [items] + [warning] + item-title: '需求物品:' item-value: ' - [item]' items-value: ' - [number] x [item]' warning: 完成後將移除物品 other: - lore: '[experience] - + lore: |- + [experience] [experience-warning] - [money] - [money-warning] - - [level]' - experience: 需求經驗值:[number] + [level] + experience: '需求經驗值:[number]' experience-warning: 完成後將扣除經驗值 - money: 需求金額:[number] + money: '需求金額:[number]' money-warning: 完成後將扣除金額 - level: 需求島嶼等級:[number] + level: '需求島嶼等級:[number]' statistic: - lore: '[statistic] - - [warning]' - multiple-target: [statistic]:[number] x [target] - single-target: [statistic]:[target] - statistic: [statistic]:[number] + lore: |- + [statistic] + [warning] + multiple-target: '[statistic]:[number] x [target]' + single-target: '[statistic]:[target]' + statistic: '[statistic]:[number]' warning: 完成後將扣除統計資料 + # Contains a text generated inside [rewards] lore rewards: - lore: '獎勵: - + lore: |- + 獎勵: [text] - [items] - [experience] - [money] - - [commands]' - item-title: 物品: + [commands] + item-title: '物品:' item-value: ' - [item]' items-value: ' - [number] x [item]' - experience: 經驗值:[number] - money: 金額:[number] - commands-title: 指令: + experience: '經驗值:[number]' + money: '金額:[number]' + commands-title: '指令:' command: ' - [command]' - level: - lore: '[text] + # This part generates description text for levels object in all GUI's. + level: + lore: |- + [text] [status] - [waiver] - - [rewards]' + [rewards] status: completed: 已完成 completed-challenges-of: 已完成 [number] / [max] 項挑戰 locked: 已鎖定 - missing-challenges: '還需要完成 - + missing-challenges: |- + 還需要完成 [number] 項挑戰 - - 才能解鎖此等級。' - waiver: '可略過 [number] 項挑戰, - - 即可解鎖下一個等級。' + 才能解鎖此等級。 + waiver: |- + 可略過 [number] 項挑戰, + 即可解鎖下一個等級。 rewards: - lore: '獎勵: - + lore: |- + 獎勵: [text] - [items] - [experience] - [money] - - [commands]' - item-title: 物品: + [commands] + item-title: '物品:' item-value: ' - [item]' items-value: ' - [number] x [item]' - experience: 經驗值:[number] - money: 金額:[number] - commands-title: 指令: + experience: '經驗值:[number]' + money: '金額:[number]' + commands-title: '指令:' command: ' - [command]' + + # This part generates description for the Library Entry library: author: 作者:[author] version: 使用 Challenges [version] 製作 - lang: 語言:[lang] + lang: '語言:[lang]' gamemode: 主要適用於 [gamemode] conversations: prefix: '[BentoBox]: ' @@ -1241,40 +1197,40 @@ challenges: all-data-removed: [gamemode] 的所有附加元件資料已從資料庫中清除。 confirm-all-data-deletion: 請確認是否要清除 [gamemode] 的所有附加元件資料。 write-name: 請在聊天室輸入名稱。 + confirm-instruction: "在聊天室輸入「confirm」以繼續,或輸入「cancel」以取消。" + input-repeat-count: 請在聊天室輸入重複次數。輸入 0 代表無限重複。 new-object-created: 已為 [gamemode] 建立新的物件。 object-already-exists: 物件 [id] 已存在,請選擇其他名稱。 invalid-challenge: 挑戰 [challenge] 包含無效資料,因此無法部署! - name-changed: 成功:名稱已更新。 + name-changed: '成功:名稱已更新。' write-description: 請在聊天室輸入新的描述。完成後請在新的一行輸入「quit」。 - description-changed: 成功:描述已更新。 + description-changed: '成功:描述已更新。' write-permissions: 請在聊天室逐行輸入所需權限。完成後請在新的一行輸入「quit」。 - permissions-changed: 成功:挑戰權限已更新。 + permissions-changed: '成功:挑戰權限已更新。' write-reward-text: 請在聊天室輸入新的獎勵文字。完成後請在新的一行輸入「quit」。 - reward-text-changed: 成功:獎勵文字已更新。 + reward-text-changed: '成功:獎勵文字已更新。' write-repeat-reward-text: 請在聊天室輸入新的重複獎勵文字。完成後請在新的一行輸入「quit」。 - repeat-reward-text-changed: 成功:重複獎勵文字已更新。 + repeat-reward-text-changed: '成功:重複獎勵文字已更新。' write-reward-commands: 請在聊天室逐行輸入新的獎勵指令。完成後請在新的一行輸入「quit」。 - reward-commands-changed: 成功:獎勵指令已更新。 + reward-commands-changed: '成功:獎勵指令已更新。' write-repeat-reward-commands: 請在聊天室逐行輸入新的重複獎勵指令。完成後請在新的一行輸入「quit」。 - repeat-reward-commands-changed: 成功:重複獎勵指令已更新。 + repeat-reward-commands-changed: '成功:重複獎勵指令已更新。' challenge-removed: [gamemode] 的挑戰 [challenge] 已從資料庫中移除。 confirm-challenge-deletion: 請確認是否要從資料庫中移除 [gamemode] 的挑戰 [challenge]。 level-removed: [gamemode] 的等級 [level] 已從資料庫中移除。 confirm-level-deletion: 請確認是否要從資料庫中移除 [gamemode] 的等級 [level]。 start-downloading: 開始下載並匯入挑戰圖書館。 - written-text: 輸入內容: + written-text: '輸入內容:' confirm-data-replacement: 請確認是否要以新的挑戰取代目前的挑戰資料。 - new-challenges-imported: 成功:[gamemode] 的新挑戰已匯入。 + new-challenges-imported: '成功:[gamemode] 的新挑戰已匯入。' exported-file-name: 請輸入匯出資料庫檔案的檔名。(輸入「cancel」即可取消) - database-export-completed: 成功:[world] 的資料庫已匯出完成,已產生檔案 [file]。 + database-export-completed: '成功:[world] 的資料庫已匯出完成,已產生檔案 [file]。' file-name-exist: 名為「[id]」的檔案已存在,無法覆寫。 write-search: 請輸入搜尋內容。(輸入「cancel」即可取消) search-updated: 搜尋內容已更新。 - enter-formula: '請輸入公式,只能使用 PAPI Placeholder,以及 =、<、>、<=、>=、==、!=、AND、OR 等符號。 - - 範例:%my_lifetime_count% >= 1000 AND %island_level% >= 100' - confirm-instruction: 在聊天室輸入「confirm」以繼續,或輸入「cancel」以取消。 - input-repeat-count: 請在聊天室輸入重複次數。輸入 0 代表無限重複。 + enter-formula: |- + 請輸入公式,只能使用 PAPI Placeholder,以及 =、<、>、<=、>=、==、!=、AND、OR 等符號。 + 範例:%my_lifetime_count% >= 1000 AND %island_level% >= 100 titles: challenge-title: 完成挑戰! challenge-subtitle: '[friendlyName]' @@ -1297,15 +1253,15 @@ challenges: name-has-completed-challenge: [name] 已完成 [value] 挑戰! name-has-completed-level: [name] 已完成 [value] 等級! load-skipping: '"[value]" 已存在,已略過。' - load-overwriting: 正在覆寫「[value]」 - load-add: 新增物件:[value] + load-overwriting: '正在覆寫「[value]」' + load-add: '新增物件:[value]' no-reward-this-time: 運氣不太好——這次沒有獎勵! errors: no-name: 缺少挑戰名稱。 unknown-challenge: 未知的挑戰。 - not-valid-integer: '輸入的整數「[value]」無效! - - 必須介於 [min] 與 [max] 之間。' + not-valid-integer: |- + 輸入的整數「[value]」無效! + 必須介於 [min] 與 [max] 之間。 not-deployed: 此挑戰尚未部署! not-on-island: 你必須位於自己的島嶼上才能這麼做! challenge-level-not-available: 你尚未解鎖完成此挑戰所需的等級。 @@ -1319,10 +1275,11 @@ challenges: not-enough-money: 你的帳戶至少需要有 [value] 才能完成此挑戰。 not-enough-experience: 你至少需要 [value] 點經驗值才能完成此挑戰。 island-level: 你的島嶼至少需要達到等級 [number] 才能完成此挑戰! - no-load: 錯誤:無法載入 [file]。錯誤:[message]。 - load-error: 錯誤:無法載入 [value]。 - import-failed: 無法匯入挑戰:[message]。請查看伺服器主控台以取得詳細資訊。 + no-load: '錯誤:無法載入 [file]。錯誤:[message]。' + load-error: '錯誤:無法載入 [value]。' + import-failed: '無法匯入挑戰:[message]。請查看伺服器主控台以取得詳細資訊。' no-rank: 你的權限等級不足,無法執行此操作。 + wrong-biome: 你必須站在 [biome] 生態域內才能完成此挑戰! cannot-remove-items: 部分物品無法從你的背包中移除! exist-challenges-or-levels: 此世界已存在挑戰或等級,無法繼續! no-challenges: 此世界尚未設定挑戰! @@ -1340,22 +1297,104 @@ challenges: no-team: 這是一項隊伍挑戰,你必須加入隊伍才能完成! insufficient-team: 此隊伍挑戰需要至少 [number] 位隊伍成員在線,目前只有 [online] 位在線。 member-missing-share: [name] 尚未提供他應負責的份額([amount] x [item])。 - wrong-biome: 你必須站在 [biome] 生態域內才能完成此挑戰! +# # Showcase for manual material translation +# materials: +# # Names should be lowercase. +# cobblestone: "Cobblestone" +# # Also supports descriptions. +# stone: +# name: "Stone" +# description: "" +# item-stacks: +# # Non-specific item meta translations. +# # TYPE is the item type +# # META is a content of item meta. +# generic: "[type] [meta]" +# # Non-specific meta translations. Will replace [meta] +# meta: +# upgraded: "Upgraded" +# extended: "Extended" +# potion-meta: "[type] [upgraded] [extended]" +# # Be aware, enchants are always listed below item in separate line. +# enchant-meta: " - [type] [level]" +# skull-meta: ": [player-name]" +# book-meta: "[title] [author]" +# # Custom Enchantment Translation. +# enchant: +# menting: "Mending" +# unbreaking: "Unbreaking" +# # Custom Potion Translation. +# potion-type: +# water_breathing: "Water Breathing" +# # You can also create specific item translations +# # Like translate all potions. +# potion: +# # This will overwrite generic translation. +# name: "[type] [upgraded] [extended]" +# # Type is either specific translation or potion effect. +# uncraftable: "Uncraftable" +# water: "Water" +# mundane: "Mundane" +# thick: "Thick" +# awkward: "Awkward" +# night_vision: "Potion of Night Vision" +# invisibility: "Potion of Invisibility" +# jump: "Potion of Leaping" +# fire_resistance: "Potion of Fire Resistance" +# speed: "Potion of Swiftness" +# slowness: "Potion of Slowness" +# water_breathing: "Potion of Water Breathing" +# instant_heal: "Potion of Healing" +# instant_damage: "Potion of Harming" +# poison: "Potion of Poison" +# regen: "Potion of Regeneration" +# strength: "Potion of Strength" +# weakness: "Potion of Weakness" +# luck: "Potion of Luck" +# turtle_master: "Potion of Turtle Master" +# slow_falling: "Potion of Slow Falling" +# stone_shovel: +# # This will mean that only stone shovels will not show +# # meta information. +# name: "[type]" +# +# # Showcase how to support multi-linguistic challenges +# challenges: +# # Database ID name. +# example_challenge_id: +# name: "Translated Name" +# description: |- +# Translated Custom +# description +# reward-text: |- +# Translated Reward +# text +# repeat-reward-text: |- +# Translated Repeat +# Reward text +# levels: +# # Database ID name. +# example_level_id: +# name: "Translated Name" +# description: |- +# Translated Custom +# description +# reward-text: |- +# Translated Reward +# text protection: flags: CHALLENGES_ISLAND_PROTECTION: - description: '設定哪些人 - - 可以完成挑戰。' + description: |- + 設定哪些人 + 可以完成挑戰。 name: 挑戰保護 CHALLENGES_WORLD_PROTECTION: - description: '啟用或停用 - + description: |- + 啟用或停用 玩家必須位於 - 自己的島嶼上 - - 才能完成挑戰的限制。' + 才能完成挑戰的限制。 name: 挑戰島嶼限制 hint: 島嶼外無法完成挑戰 version: 12 From 1ac50cb9a2c588ada1e6cf6df6373f197a5256e5 Mon Sep 17 00:00:00 2001 From: Drownek Date: Tue, 11 Aug 2026 15:24:27 +0200 Subject: [PATCH 05/15] build: add Maven wrapper and enforce Java 21+ --- .mvn/wrapper/maven-wrapper.jar | Bin 0 -> 63028 bytes .mvn/wrapper/maven-wrapper.properties | 2 + mvnw | 332 ++++++++++++++++++++++++++ mvnw.cmd | 206 ++++++++++++++++ pom.xml | 21 ++ 5 files changed, 561 insertions(+) create mode 100644 .mvn/wrapper/maven-wrapper.jar create mode 100644 .mvn/wrapper/maven-wrapper.properties create mode 100644 mvnw create mode 100644 mvnw.cmd diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..7967f30dd1d25fe1b79a4a6e50e2aaa0e425c02c GIT binary patch literal 63028 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 O(fWavBF*XjpZ){(@cW1W literal 0 HcmV?d00001 diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..ab8de201 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar diff --git a/mvnw b/mvnw new file mode 100644 index 00000000..5e9618ca --- /dev/null +++ b/mvnw @@ -0,0 +1,332 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ]; then + + if [ -f /usr/local/etc/mavenrc ]; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ]; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ]; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false +darwin=false +mingw=false +case "$(uname)" in +CYGWIN*) cygwin=true ;; +MINGW*) mingw=true ;; +Darwin*) + darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + JAVA_HOME="$(/usr/libexec/java_home)" + export JAVA_HOME + else + JAVA_HOME="/Library/Java/Home" + export JAVA_HOME + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ]; then + if [ -r /etc/gentoo-release ]; then + JAVA_HOME=$(java-config --jre-home) + fi +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin; then + [ -n "$JAVA_HOME" ] \ + && JAVA_HOME=$(cygpath --unix "$JAVA_HOME") + [ -n "$CLASSPATH" ] \ + && CLASSPATH=$(cygpath --path --unix "$CLASSPATH") +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw; then + [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] \ + && JAVA_HOME="$( + cd "$JAVA_HOME" || ( + echo "cannot cd into $JAVA_HOME." >&2 + exit 1 + ) + pwd + )" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr "$javaExecutable" : '\([^ ]*\)')" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=$(which readlink) + if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then + if $darwin; then + javaHome="$(dirname "$javaExecutable")" + javaExecutable="$(cd "$javaHome" && pwd -P)/javac" + else + javaExecutable="$(readlink -f "$javaExecutable")" + fi + javaHome="$(dirname "$javaExecutable")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ]; then + if [ -n "$JAVA_HOME" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="$( + \unset -f command 2>/dev/null + \command -v java + )" + fi +fi + +if [ ! -x "$JAVACMD" ]; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ]; then + echo "Warning: JAVA_HOME environment variable is not set." >&2 +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + if [ -z "$1" ]; then + echo "Path not specified to find_maven_basedir" >&2 + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ]; do + if [ -d "$wdir"/.mvn ]; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=$( + cd "$wdir/.." || exit 1 + pwd + ) + fi + # end of workaround + done + printf '%s' "$( + cd "$basedir" || exit 1 + pwd + )" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + # Remove \r in case we run on Windows within Git Bash + # and check out the repository with auto CRLF management + # enabled. Otherwise, we may read lines that are delimited with + # \r\n and produce $'-Xarg\r' rather than -Xarg due to word + # splitting rules. + tr -s '\r\n' ' ' <"$1" + fi +} + +log() { + if [ "$MVNW_VERBOSE" = true ]; then + printf '%s\n' "$1" + fi +} + +BASE_DIR=$(find_maven_basedir "$(dirname "$0")") +if [ -z "$BASE_DIR" ]; then + exit 1 +fi + +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +export MAVEN_PROJECTBASEDIR +log "$MAVEN_PROJECTBASEDIR" + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" +if [ -r "$wrapperJarPath" ]; then + log "Found $wrapperJarPath" +else + log "Couldn't find $wrapperJarPath, downloading it ..." + + if [ -n "$MVNW_REPOURL" ]; then + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" + else + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" + fi + while IFS="=" read -r key value; do + # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) + safeValue=$(echo "$value" | tr -d '\r') + case "$key" in wrapperUrl) + wrapperUrl="$safeValue" + break + ;; + esac + done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + log "Downloading from: $wrapperUrl" + + if $cygwin; then + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") + fi + + if command -v wget >/dev/null; then + log "Found wget ... using wget" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl >/dev/null; then + log "Found curl ... using curl" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + else + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + fi + else + log "Falling back to using Java to download" + javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaSource=$(cygpath --path --windows "$javaSource") + javaClass=$(cygpath --path --windows "$javaClass") + fi + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + log " - Compiling MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/javac" "$javaSource") + fi + if [ -e "$javaClass" ]; then + log " - Running MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +# If specified, validate the SHA-256 sum of the Maven wrapper jar file +wrapperSha256Sum="" +while IFS="=" read -r key value; do + case "$key" in wrapperSha256Sum) + wrapperSha256Sum=$value + break + ;; + esac +done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" +if [ -n "$wrapperSha256Sum" ]; then + wrapperSha256Result=false + if command -v sha256sum >/dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c >/dev/null 2>&1; then + wrapperSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c >/dev/null 2>&1; then + wrapperSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $wrapperSha256Result = false ]; then + echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 + echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 + echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + exit 1 + fi +fi + +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$JAVA_HOME" ] \ + && JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") + [ -n "$CLASSPATH" ] \ + && CLASSPATH=$(cygpath --path --windows "$CLASSPATH") + [ -n "$MAVEN_PROJECTBASEDIR" ] \ + && MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +# shellcheck disable=SC2086 # safe args +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 00000000..4136715f --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,206 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. >&2 +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. >&2 +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. >&2 +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. >&2 +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash;"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Error 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Error 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Error 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml index 980f2292..f2f97282 100644 --- a/pom.xml +++ b/pom.xml @@ -270,6 +270,27 @@ + + org.apache.maven.plugins + maven-enforcer-plugin + 3.5.0 + + + enforce-java + + enforce + + + + + [21,) + Incorrect Java version! This project requires Java 21 or higher. + + + + + + org.apache.maven.plugins maven-shade-plugin From 638e68d61b6d40e6a4baf4a1b66466788a51314e Mon Sep 17 00:00:00 2001 From: Drownek Date: Tue, 11 Aug 2026 15:24:27 +0200 Subject: [PATCH 06/15] test(e2e): automate Challenges jar build via Gradle Exec Previously, developers had to manually run 'mvnw package' before running e2e tests. This commit adds a 'buildChallenges' Gradle task that runs the Maven wrapper automatically, resolving the Java toolchain and finding the compiled jar without manual intervention. --- e2e/build.gradle.kts | 50 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/e2e/build.gradle.kts b/e2e/build.gradle.kts index add50300..c48e2618 100644 --- a/e2e/build.gradle.kts +++ b/e2e/build.gradle.kts @@ -1,8 +1,16 @@ import java.net.URI +import me.drownek.plugwright.PlugwrightTestTask plugins { // Plugwright: boots a real Paper server, deploys plugins, drives Mineflayer bots. id("io.github.drownek.plugwright") version "2.0.2" + id("java") +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } } // --- Dependency jars ------------------------------------------------------------------------- @@ -31,15 +39,39 @@ val bskyblockJar = cachedJar( "https://github.com/BentoBoxWorld/BSkyBlock/releases/download/1.20.0/BSkyBlock-1.20.0.jar" ) -// Maven-built Challenges jar (version/profile suffix varies: -SNAPSHOT-LOCAL locally, plain on CI). -val challengesJar: File = (file("../target").listFiles()?.toList() ?: emptyList()) - .firstOrNull { - it.name.startsWith("Challenges-") && it.name.endsWith(".jar") && - !it.name.contains("sources") && !it.name.contains("javadoc") +val javaLauncher = extensions.getByType().launcherFor(extensions.getByType().toolchain) + +val buildChallenges by tasks.registering(Exec::class) { + workingDir = file("..") + + val isWindows = System.getProperty("os.name").lowercase().contains("win") + val executable = if (isWindows) listOf("cmd", "/c", "mvnw.cmd") else listOf("./mvnw") + commandLine(executable + listOf("-q", "-DskipTests", "package")) + + // Maven needs JAVA_HOME to be Java 21+ as per our project toolchain + environment["JAVA_HOME"] = javaLauncher.get().metadata.installationPath.asFile.absolutePath + + // Explicitly define the expected output file + val outputJar = layout.buildDirectory.file("Challenges.jar") + outputs.file(outputJar) + + doFirst { + logger.lifecycle("Building Challenges project using Maven Wrapper (mvnw package)...") + } + + doLast { + val builtJar = fileTree("../target") { + include("Challenges-*.jar") + exclude("*sources*", "*javadoc*") + }.singleFile + + builtJar.copyTo(outputJar.get().asFile, overwrite = true) } - ?: throw GradleException( - "Challenges jar not found in ../target — run 'mvn -q -DskipTests package' first." - ) +} + +tasks.named("plugwrightTest") { + dependsOn(buildChallenges) +} plugwright { minecraftVersion.set("1.21.11") @@ -52,6 +84,6 @@ plugwright { writeFiles { file("plugins/BentoBox.jar", bentoboxJar) file("plugins/BentoBox/addons/BSkyBlock.jar", bskyblockJar) - file("plugins/BentoBox/addons/Challenges.jar", challengesJar) + file("plugins/BentoBox/addons/Challenges.jar", file("build/Challenges.jar")) } } From c9415f6d616c369cc994a5da86e30230f6866608 Mon Sep 17 00:00:00 2001 From: Drownek Date: Tue, 11 Aug 2026 16:16:37 +0200 Subject: [PATCH 07/15] fix(e2e): flexibly resolve Java 21+ toolchain and address PR feedback - Fix mvnw execution permissions for CI/Unix - Declare task inputs for buildChallenges to fix caching - Use clean package in Maven to prevent singleFile crashing on stale artifacts - Resolve JavaToolchain dynamically only if Gradle runs on < Java 21, allowing devs on Java 22+ to build out of the box - Remove redundant Maven run from e2e GitHub Actions workflow --- .github/workflows/e2e.yml | 2 -- e2e/build.gradle.kts | 35 ++++++++++++++++++++++++----------- mvnw | 0 3 files changed, 24 insertions(+), 13 deletions(-) mode change 100644 => 100755 mvnw diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 6a9787c7..2428c51a 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -61,8 +61,6 @@ jobs: # (mineflayer/minecraft-data must support the target Minecraft version). key: e2e-npm-${{ hashFiles('e2e/src/test/e2e/package-lock.json') }} - - name: Build Challenges jar (Maven) - run: mvn -B -DskipTests package - name: Run E2E tests working-directory: e2e diff --git a/e2e/build.gradle.kts b/e2e/build.gradle.kts index c48e2618..bbe0f7a4 100644 --- a/e2e/build.gradle.kts +++ b/e2e/build.gradle.kts @@ -4,13 +4,6 @@ import me.drownek.plugwright.PlugwrightTestTask plugins { // Plugwright: boots a real Paper server, deploys plugins, drives Mineflayer bots. id("io.github.drownek.plugwright") version "2.0.2" - id("java") -} - -java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(21)) - } } // --- Dependency jars ------------------------------------------------------------------------- @@ -39,17 +32,34 @@ val bskyblockJar = cachedJar( "https://github.com/BentoBoxWorld/BSkyBlock/releases/download/1.20.0/BSkyBlock-1.20.0.jar" ) -val javaLauncher = extensions.getByType().launcherFor(extensions.getByType().toolchain) +// If Gradle is running on Java 17, try to find a Java 21+ toolchain to satisfy Maven/Paper. +// If Gradle is already running on Java 21+ (e.g., 22, 23), don't force a strict toolchain lock. +val currentJava = JavaVersion.current() +val javaLauncherProvider = if (currentJava < JavaVersion.VERSION_21) { + extensions.getByType().launcherFor { + languageVersion.set(JavaLanguageVersion.of(21)) + } +} else { + null +} val buildChallenges by tasks.registering(Exec::class) { workingDir = file("..") + inputs.dir(file("../src")) + inputs.file(file("../pom.xml")) + val isWindows = System.getProperty("os.name").lowercase().contains("win") val executable = if (isWindows) listOf("cmd", "/c", "mvnw.cmd") else listOf("./mvnw") - commandLine(executable + listOf("-q", "-DskipTests", "package")) + // Use 'clean' to avoid multiple jars causing singleFile to fail + commandLine(executable + listOf("-q", "clean", "package", "-DskipTests")) - // Maven needs JAVA_HOME to be Java 21+ as per our project toolchain - environment["JAVA_HOME"] = javaLauncher.get().metadata.installationPath.asFile.absolutePath + // Pass the correct JAVA_HOME to Maven if we needed a custom toolchain + if (javaLauncherProvider != null) { + environment["JAVA_HOME"] = javaLauncherProvider.get().metadata.installationPath.asFile.absolutePath + } else { + environment["JAVA_HOME"] = System.getProperty("java.home") + } // Explicitly define the expected output file val outputJar = layout.buildDirectory.file("Challenges.jar") @@ -71,6 +81,9 @@ val buildChallenges by tasks.registering(Exec::class) { tasks.named("plugwrightTest") { dependsOn(buildChallenges) + if (javaLauncherProvider != null) { + javaLauncher.set(javaLauncherProvider) + } } plugwright { diff --git a/mvnw b/mvnw old mode 100644 new mode 100755 From 734f776891b588c00b9697e2c65ba60e1f3f5f8d Mon Sep 17 00:00:00 2001 From: Drownek Date: Tue, 11 Aug 2026 16:25:42 +0200 Subject: [PATCH 08/15] fix(e2e): restore java-base plugin for JavaToolchainService support --- e2e/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/e2e/build.gradle.kts b/e2e/build.gradle.kts index bbe0f7a4..74e87878 100644 --- a/e2e/build.gradle.kts +++ b/e2e/build.gradle.kts @@ -4,6 +4,7 @@ import me.drownek.plugwright.PlugwrightTestTask plugins { // Plugwright: boots a real Paper server, deploys plugins, drives Mineflayer bots. id("io.github.drownek.plugwright") version "2.0.2" + id("java-base") } // --- Dependency jars ------------------------------------------------------------------------- From 73193eeb571a69e57dd0ed21a57323a4049f0c37 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Aug 2026 01:07:18 +0000 Subject: [PATCH 09/15] Bump js-yaml from 4.3.0 to 4.3.1 in /e2e/src/test/e2e Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.3.0 to 4.3.1. - [Changelog](https://github.com/nodeca/js-yaml/blob/4.3.1/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/4.3.0...4.3.1) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 4.3.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- e2e/src/test/e2e/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e/src/test/e2e/package-lock.json b/e2e/src/test/e2e/package-lock.json index 6a38b7c2..0319656d 100644 --- a/e2e/src/test/e2e/package-lock.json +++ b/e2e/src/test/e2e/package-lock.json @@ -295,9 +295,9 @@ "license": "BSD-3-Clause" }, "node_modules/js-yaml": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", - "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", "funding": [ { "type": "github", From be008698b7293c7cb075baa9f964ebc0f1fd1964 Mon Sep 17 00:00:00 2001 From: tastybento Date: Tue, 11 Aug 2026 20:09:04 -0700 Subject: [PATCH 10/15] build(e2e): bump Gradle wrapper to 9.7.0 so ./gradlew runs on modern JDKs Gradle 8.10 cannot start on a JDK it does not recognise. On a machine whose default JDK is 25, every ./gradlew invocation in e2e/ died before evaluating the build script with nothing but: * What went wrong: 25.0.1 This pre-dates the rest of this PR (it reproduces on develop unmodified), but it defeats the "just run ./gradlew plugwrightTest" workflow this PR is adding, so fix it here rather than leave the new entry point broken for anyone not pinned to an older JDK. - Wrapper regenerated with the documented two-pass `wrapper` task run, so gradle-wrapper.jar is the real 9.7.0 one. Its SHA-256 is 7a9ce74cff467ca1bf60a4fcd9f05185acceda4d0f382434d393e17864262c5d, matching the checksum Gradle publishes for gradle-9.7.0-wrapper.jar. - distributionSha256Sum pinned so the downloaded distribution is verified rather than trusted. - buildChallenges switched from `by tasks.registering(Exec::class)` to `tasks.register(...)`. Gradle 9.6 deprecated the delegate form; without this the bump emits three deprecation warnings and flags the build as incompatible with Gradle 10. Verified on macOS/arm64 with JDK 25 as the default: ./gradlew buildChallenges succeeds with no deprecation warnings. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01AyrUvHMduHzV4hFj84PExn --- e2e/build.gradle.kts | 2 +- e2e/gradle/wrapper/gradle-wrapper.jar | Bin 45633 -> 47505 bytes e2e/gradle/wrapper/gradle-wrapper.properties | 5 ++- e2e/gradlew | 6 ++-- e2e/gradlew.bat | 35 +++++++------------ 5 files changed, 20 insertions(+), 28 deletions(-) diff --git a/e2e/build.gradle.kts b/e2e/build.gradle.kts index 74e87878..144a3d32 100644 --- a/e2e/build.gradle.kts +++ b/e2e/build.gradle.kts @@ -44,7 +44,7 @@ val javaLauncherProvider = if (currentJava < JavaVersion.VERSION_21) { null } -val buildChallenges by tasks.registering(Exec::class) { +val buildChallenges = tasks.register("buildChallenges") { workingDir = file("..") inputs.dir(file("../src")) diff --git a/e2e/gradle/wrapper/gradle-wrapper.jar b/e2e/gradle/wrapper/gradle-wrapper.jar index f8e1ee3125fe0768e9a76ee977ac089eb657005e..eddabd2eef8d94a5437d6168ff9c87a78ff725b3 100644 GIT binary patch delta 39258 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%0D}_YK{Q?32MR^ESETLLJ>zQ@qcaOVwT<` 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 delta 37448 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 O00CYA5YPTOBmD&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,29 +65,18 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% From 93889c15fcdf55b7de8f11a6556d6717c30f5431 Mon Sep 17 00:00:00 2001 From: Drownek Date: Wed, 12 Aug 2026 15:16:24 +0200 Subject: [PATCH 11/15] fix(e2e): migrate to script-only Maven wrapper and pick newest jar - Switch Maven wrapper to script-only type, dropping the committed binary jar - Remove clean from buildChallenges Maven args as requested - Pick newest built jar dynamically to avoid singleFile conflicts --- .mvn/wrapper/maven-wrapper.jar | Bin 63028 -> 0 bytes .mvn/wrapper/maven-wrapper.properties | 3 +- e2e/build.gradle.kts | 6 +- mvnw | 483 ++++++++++++-------------- mvnw.cmd | 345 +++++++++--------- 5 files changed, 392 insertions(+), 445 deletions(-) delete mode 100644 .mvn/wrapper/maven-wrapper.jar diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 7967f30dd1d25fe1b79a4a6e50e2aaa0e425c02c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63028 zcmb4q1CS^|ljgjcH@0otwr$(CZQHhO+qV72wmoxial8B9?fnG~W9XQvmB954jDBa!| zNc#NR*+3@;Ud413!#s1`?>g#(_$H7D)m#yN3CFB3#cg^11e^UTu%gCz#*^XWpvA=0 zhv_OXm@wi}1?A-`%mh)oO)C5c54*d;j;Hx>J~Q20-{8Of zMDuUGK=ZHCH2;5VS^fuF{#7USf7SV)p_nN;{LB8YF37*3i2Pr53JJ>z%Loa}2#O0U zR>$x|0MbJVzisl^jPb4zA&czN=0<(g&o&UyWr84T4=|4uM|{fs3Kg z(YLtUYN*=Zu+UU})fkom?q*7LHXqx<3P(R)F~8R@%1CQ0B5J=cpnI>- zsM-SXqJE1&kYtIO)rBAf?r(@tK;feXJAuGe-j3fgzuQ?C$0E>m0sm83y@Rx8@ZV zFxN0T>96)9qNSBOO>lCsvt=An4O`{vs^FtXOKFs!AkC(d1v@5jb!4on&Ia^xq`060 z#y~TtN_*GaLdK`M(OZWme70i1i_k4XejO-YxuDP5Czqy2&bDHCbgwO|Z{U2pijGT| zPwX~BD>7aSOO4n1t#Ozp7;r%Od3G;_5WfOjjGuZGg*taJEqd;}RC^~Wu}mF90d$2K zTt~=w08_tOQqY-sNSXJ((S4Rn2SZ<`=S6U`%RR}3G&?Xt>SDj^0eS<# zy0g!E4fS7fTw>c}(unuGgT;XJNI-Q-JV{1F!G1P+AZ}~}n3@ncD@H2pP->cE0{oh^ z`+zWcIL4cUGj(uz*aKOp`-zb~s&x;9M2d#bspAl;6X&3H`+*2%aIBm$09yxL(4S}B zL@oSsUWC{jwS`JmcCb-CVK^fcTM=8q?R7h64ypdX*ev}p0MgBu14&d3kOIxUa=?I5 zSXjIO;r~p#v$*T49VG>d;a^CuO)(`Q)k)bpgLY=Ue;dePH;m9E`HVDY9(RV$6|hl@-gwBC*_o58EB3i^UnOu{1&W_)5GHNJjjU z-|1VC_OoWS0pR3v`~8Q1UN|Gsg9q7+aNrJ61HMb@=z85E9uZl{cmwCayRa{fIc?wk z{@!?5XKFv)L+_{atG*JlH(V_IS48%A348-WFuBGvXXc_x)@%N-^|c{7%BjJkRssV#WFw&_#Wuos*-24Rw3iI<66*4S571V{UKp4L`&0Bb{&zN(l7cteHBnC~1IF`~k>~v`iM;t`VV&#?YuS~l?sHrVthO}#5{g+CNE|z-pr{ZRQYRa8fKws9RGxJ2pF{zIu}Vs zBI689x!s+(jO5dj*)nl}%44tX=iGAR^7PmJ)e}_0jXj>H;l>+xoP+7d;d(NEU%C`~ zJ=Gf}BC>`oI8PGtQyTf{l6oTnnRwQNi2+v`Ji{&jDcEr88Z)Bfp8?Y=iGC0U3}WmS z#kZtCwBqX!Ltrf4h)YTQqed4-`Ql3Lrp~WCpbz44NABF%eBj!oS^Wv^(#W?;J@v!o z$;P`L>q(O@Af{DHxW*9hV5b1<>UeW1w0Ci#rPRqb065Q`eC}ICNrPX zhyI#pY=?n31kAN#awX@lTLeQKQYH`eR$~7${rLeTU=8pnkeDNfVVK-ccrzSrnvw>7hv<-ktwaXHEg zVzNqb^a~XXKO_+vArshk*svPMtkROB>vOQQiA!QRabO+N&aLmy9()%w+%tqNOnwa# zq;;t5J;$%sPWeUdUqLUYM(>qCExJfvVW+?=Oh?PXWK|&P{?^AZqPfGQ@7(=Gu14P? zqfRSVpKATQP-~?C?PK)f@g%%WCf8PLY z7<%x6icBEZx+QnR$YedgF0pCJi~!_ueV!L>g(pDg;rxF4$PC`-gUN75TKgK{I9|=F zVFzwRUaFNzXS(arqpw(2-0R`d;q7e$=iV-z$jr`9jql@ZwJIMJU)`D-ziYFeUp_-; zWs;=xL6piYB+}?Yjtb~@=K#_)=@A$No)GnVQy)iP9~XdCJs#~^-JO~>-yUC!Pv<>w zyxKe6U+_&@pLJfnT|empr`z{F&fUkWpeQ;cSNkwn&wF3{GFv`vo!#oXj?G7#10c32 zd_OoW%T5=3tc+X8GK0WerqZ^|3yvIi(DT8ua-YOQ)5pbJ)=n^N@Hnh}%`QQgGf5mR z<51_{ImspUZ^9SmjFa^*sq9`bB*Vft&0D7-G_$E{?!a@oHhA1>AYRLJb%;(uGMt#r zL77xwdHA^KP8OSHdb-6ORQuMh^yo(;=N)?J6w}oY{K^=eH7k9_)Qj5H~B0o2Fu9cr9MZe!oLZ zJKXS3fuP%-Kt87;=edsS zkX?LwZMa>(Xz3G}%%D#mrb_0|X#h9p3@(Rlt&BOVEL2|9Qx?N6S zf-`Jn;dj+%iOv;(w{;J$3!F-=)!5}qqwVQk_{DD+cvrY?NIFz)#Duoah?q4aYTM)_ z?ShHG-r9?jk6-hH;m_1hb|xuBx?MmdB%4@31@$R~=1HQ>$YVI**pp~|Zk8#rJXdoI zp*OOeKHuI%jW3V4Iv+uvEo!-Fot}#YL?WmfGfe?2AGz3mcf30;!ZG)YI?f7X{F5hg zB#K2uo6WCQRaH%Owi`sWm)6F1FaC&kClAtG10c-fwwCs=_Il5@XoBYtasSR2Dh=7E zCDNj~K;AM)!-xPTPf)o?Jja_xWr+hI#BU*bNxUg>yx{n6BEwN^c@I#x9U~H?{(H4yNX+d8 zc*H8IOfy1c<9p#KXm0&qXO50u$Os+@!G3G?e7600IDeT4E;6vA zuLtv`2!g%Lc00V|w0&53e<3K95bF-iUP}{hp@e)6a<%2RS-z?V zZGJUvk-yJ*=y#zHxwmPta`Q6>*AwB*WfuF%6#Gs4)MfAY!=5Mr&X6d*Q=THfm@pc= zzx7EoFty_RRQr_CUYCy3Zvw&)bGBG8r;>NsQ8?k$fV2pkGC;u;?$r4TjruCn<7VLP zDXI;P=8DbqQL4#u_N*w&kaSn3&3SA8O%v$Gq{VX*;7daca-j08&SG=5boIglQyDWE z_cq?JGQG+^>}cTa@vMxAXq6@nYEyIKZIwD{K5N}e5v*3qQ~7!zPT+k^W{4o{izMs0 ztEARKN=_E6!E7w8KZ%P{F9maro-7uaj%IHfyuFBQGfpE)Z=L6pbwzT)5Sii|#rEb~NyY<}GkAj(kqSCOyd z4b_&!{?x-A)K8udIJw%;=XFXC?#M5OxL;LgGiAmc?+FKvW~vs7lm%{byFMkd9cIao z4Jx(8mB`-Vg7Wv&8ZO03lByZy3C|899iMR#w7UTQWpe42%6YBcrCo-Y$6L1`bfJY~ z5JOu+(y7(%+9hLQ5uyE;f6moHA(<-`TpvYjE~S7?@{`<^hV{8f;GC;QbS~&EG~fmg z+ywgJk!APGV9!M!fjh#tz&8zs*;0SQ{C2aq?9C`5i;?%{bP%4*iVk4k(59Q3`s7K) zv(A;H4@U%ys9xLz*2ZgQckx**OhW*hZp=f@GNP{yRP8tS-!u)-8#|DsD6wye?>^{I zY)Mm%1+n64#5cRT-gvhPmL^}E;~SRUGY8gHv4_!xZ*yc6VWA(?s-u}(54`eZ(a5r$ zB`NnMB#!{>rmd?bCv(qi2ADuU4j!*CR5O8UOjDFo(ck6zb@zb17x=bey@bPRRncrU z;;pNPm^E(QGHmy=PDas`FV7%o?T?Egmb+?Y9#}pgkQ_a`gsSNYZ>(+jha0`^p!B4l zL%0eA6RNAQAO_gK({_A1fZh$ttf(njb(@|dy`Cf+BGpd3Usc%)TKA=+B{sNRbHxJj zlKDE`Nkzg-aJbPeW{+OGp%*RlF0sT%ak%x69+gI=Dx+q1Q^%`o#)R4;I09!7*-Lcz z!OeeKjxzcF$s+kkVbOR?u^j;1g$a1)2_Wx>VFoe9ai}7*m^3A#1GAOJ3zt{!HX$PQ zE@Bl{>%>7tzLJhxP%$x)s@l!w3t{nw*?(TXQiq&adQx0P%;m92aV7DfA)mNgC!Nd1 zjlw)l+G2c{+zRR3;loJRwwe}u5cZA`m{;Wvq~Yh*{21_&9M z?SewgY6ltZ)O{_YfKK|`C%7qkOn{-A9`HVgF2}7R4dkFA3)(G>&xri)$t!R> z8P)rEX`G9@o*nSS5VTb~%=VD=Vz!{=8ckgk=Y3_HC%UJKoi0mL#J7+cdb$wVcOS#E z>EK;ppk-d8B^yy)#606&egEqnbCheJtZdMMZqfdylj*0D54veXypT}b9Q}5C>O(r? zs&;SD9_(EX@Z)?PQcEFjr`zVmu#OHoXnV@BH%TBCtuG_i?A|Y}!`30kwHpqPrah@e z`L}1uESK!wDBZnPCys&RZ=4;D@(1!ykY3?1jo1U%SMFaOVb-re-(oeq%=(s9U+I=N zi3kKo9L=|oMc})_BE$p9m7WI~7cZ}RC(=l&`MQIPfp?IVX}NeQsK5>RLT1pBfU9@v+`M&N#vV$KazbGg*VcO0?0o)fz2iR%1zVwy zwPJt(0D^xDI}HD9@)R;Q(Ra3T60&u*v9i@SGIk)M|M$65$yyeXAI=8_0(4a0GMS*q zU!flOurF1XdFWUJ(LfWk!Ws&9YJuh|{eos)2jA;~^bB;^Y#;Vk6y3B|Ob*Xq(#FNa zCdb{x)bwWc=7#qd*DxcbAe4IXCe6;#bc|i6m#mnp?!&fr{&qt>22kOYH+u}42vrnE z9oL~D>tEqzo7c5kWZWRkGvGcYdkE2>QM-?PmL>`6`;tH*xu~W%J0z zbU^fGo8ewfp!(F8B!WH~iNKL_+l=KjESf?3Wr`_b%ts061Jt6aoUQvhM_^{VlqEF5 zae0bfSgIE}#n*Mqob9U%UyhMDv%B2M2J3S?qe)Dh{t*JzSu@sEJ=H*rg>w6`_IYjz z7UR-b<7}`#kK@w#18i)<2J`Z&^xXn$aj{~O{~;OLII5c%19O-Fh&tYa6iY?cBRs@M8eRc0RpMlkw{XfY*)P6N?fY|9EyT&ZtncfPG-h7PUeRCPPYHP=&M$= zv_#}b;%1fZw9n+xVy^Ge*wjc=Ym8QrClC;a4^o0$4tQK-!cI&!Vx5wCe^rf`0|EB+ z$FxIrx!z)b$!c^p@%es#2I^zT*$~qk6JUtekAhnPRCX2CT*6qe4%a^G z^pt4YRA{ffFFa*>vZy;@1*#`p{v6>iGq%(Q?yBNOcWCmhTbPGFv#cd?$^#>$<=R=K z1s81pEQwBKI6)eL{6rc7JAkg<9Bz^K!j&*K z1WZJsDc#$J&}S$xgXq0}mO>D@P#9H#1%qrqCl6D}(WO0^Emdd}v6CtKMw7so^n=f4 zh+qYqeTUN#8yKP9YOy1YHlNCJ#`(3@4nqN*uabmt$(257t8BHB!_3JdI`%C8r{a(m zT?5>ONWb9x?OwXHnR=PCe)}*=5!#}lojl3(*q)&rQ%B5A^Q)FLPb!Te`=&E7s9kF- zq1Tp`G07n?jUst^mh?FlY`Fg%>{(<^p80Kp5qmsq5Gh(!;Jx`qQrWyg7hS_mh)hc> zlW&P2eF>^{DyK7XsAc3DJ)c8oqnKGEuskVGvzjocGw|k(Dok#GyoKdu?HFe00#>I zfbM@3p#MH>s)OqxuBLzIP+N`|2=D<~@k=1pye0(*(r|*Zu=NkAQX3lL&GBPw0=kQ! zM+3OFo{^X@uyCht>s+>MGMc|onV0FfXA;=$TM&IRSCSIa@e?< zwgRbcTI;+qrQxwr2W)dF!IHR;9c2u2;TXc_W*4u$P|tWQ6>C%{GN>WWt!1w_Q1{>! z)P^-*Co|!pIKfcL$OycN)?Cf_&<$+5LWk|!yVb@on7Fm3^hd2*R9H#xsp{ZxpIv;9 z?@yiJT2LlZm++v;mX>ksq1PY!hk8$^?*tJteXL!6tqWv64=HP0y8F``jhRUotyKpXu9jEF&EU&n#54ZVOKi}FbI zq^64=rgL4;t&D}>cF33GY1n~2ndVM7%mrsCLf0NB6V9$ebwx-dA~w1Og)X@`Tobc} z5F2d*&3%(IVH#Gb)=%7K>*d9S4!Z}2BX6fPNZ%#BdyKrtW;Q)F#)ZaKy?Kn_FPUyA za9n+Wp&+KXouCC&Vz^e4Q#?ya5Jz%ZZtNp>mxb!pFqSw&G9!ZYYf|em&2>@%&qc zV$32fQ2h$SMt6G1@S0pxT<;*^A<~jt;W#Tql>dn3^vo$YXSS$9ky=v0dOQ{WL2B2G zOsp?R(St>K455jE{beSuAYxHU(qZi^Mlfx36WJ>_9k=JHdbilTahdOZdH~ zIRw$7UAUi9T{MN}5t(7VsR}(dpI_t|5hEu_pIR~~3Q_&&a9#x3t47Z!dYMjWFW@u*n_ z_99Sf4KFFyMHI>G{o4Au)UKb9QY{nSsy)KjGCvCp(=2{T5Q@&wFMKboTsb?L!Ps5V z@OokQZf?skWs$Wg^CHQ+?jB>`=&rnd#i+tI#?(ZSx2BL;vAVLDqiRWAFPXuUJK%FY zOm|Ap2=o$T<4k4HIH4s+jGi!Bd65o>zA0oZ96G0sqH-f}oN_fiiSKaZVB^^2%ohb; zLLUg;>fK37-;9qn~e23?E!yzE8wT&jyd21d)o0 za!&Ego&a8j+fj_~-@X$rUgI61&M(e$H*1BHnLjOeDCNuCu zqd1w5a2aPCy>2NMLSXrP4eZJ??{B{90{@imalY2{Q5!3jm^f!T+t4$+8Dezo^}Pm; zu6@{GX|=5H9J*-Mno}_k3@Yq&5poVqQ&Zxab8nS~y;r5sX}MT-axqOjSe798`u zzGwws20x_lhrC=gptddhn}*kt!A6FWtc*_(V}>Yn$PI(Yw80e#m`9>mJa00}w6*Ff zTRk4I`dHZ5-;=0tQsT0%JC_+S0)+(L8%${~T`gG^t`W3Q7-W*PL}C}$Y*1g?V3RTc z84?m69DTSCE5uT0xWR7a$Xd;gYP6hqZvALd>VOl>mxR0YU+CFwG@LlKz{0jtl|H`5 zcNi!x6^6C-tt8WWBkN)TdZLvzA=T=Q*y&%l>BmaaiVqh-A$DZP8~QTrPMLtc#9Xw? zF_XE9dCvgO zrdH{nq1j_zJ9z#@lFn4SWd9(RzoaF5x*lK&VMtRN)}5T}T0{j+EUC=2Vv(}OAG?h#^~K%Lr0^tO(_Rb!~MokwJ^Ch>(Ur6K`r5o z#CU8Hu$E@>7CH5|dC4!0O_!r&aQ8_}U#tP@xNLv8>@q<$pDLhNtqUGZe#HZ9Eor-? zy%-Ok%nh1?p6V}PrWWTeKTLLrhnx44b|q4qgBy|GZ<%=On_>o};?D7hS8IOS2BfM6 zIOy}lHld%3hYiTrnMPWpKP&uC>oIn%TAHXfI(;LSYTn@Wj-Lf`&3DhD^QoHwUgDPrE{<_cpgqKvLHy6Vz9cnm3h)t$;9I zJ#ndBd67K9O++_=HR!fB<> z_xgpB48pde(kltwV=dh-0m8I4yJ`jXkPVn{fS?Uf{MluWS~xab^C#M%=Z}+z3ly9|6 zzYoJE^nz3JNAz^-?^y_y(5esVWbn>*UF^0ZmDIci!K6~vu% zB){g9=M~lk)JzwkNM5Kv$waCr@6^NyWh(7f&eF3XdENQfKHFH?14mG zr#;x@E;M;;Mx9xx{HXZEk+VU8leBk5G1c}J^XVFFUvnFC08V;ru9WUD(}H~0Dg3!7 zC;B=Y@hb9aizZWxbmuyVz2}>7;EP|PlU@P)qnVJn?Jv{sOmM3leqaWK3Z(dSg?h^? z>=nzY^Mx@o3+pQMyVZ;E?>?Q-!e8 z(*QewT&Tz&!-Gvv;!GcovU?!(WFfC9Mousf(j-BR#+JFx)RPb)rbA(9Ply7X=Q@R8 zPc%kgiM9xM0gA2oayk1!oRUv&=}+_yF@$F`*)|N=4vJ@Xqs&`VK^^5u7+`VC+rsvS zrJ+d=SHkc-y}v1O^I3T%KD?s#UhSQBwSZMzQi^xT|C}2Thq=%nr$9q*3O7V0E5q#w zhf>xCN&0iRJNQJ3D)Gp+cqdcq3RRg_;6{Xz@PrT&Oo+PT5wMJ#3JP@z^8~`%H+oT^ z4pGC~UtladbI-DplmcFjmxq`MI#8fNla!`SB`8{mI#@{8CGtuz#c9D+pG*$hM^3&g zE&0>C=XthU;%A%XJ?PJN_A65(#3 zTg%THo##PM1(9os)BN?1?RwB>ZgyT^{eVG!X#|Bklcoq12)$9EGHbDuLpXn0Q6_4J zF9V;#iKJ@q)c&LUl00l1 zMZf?6o_{xlGyOC7#q=G`_^nKB9n77~tW}I1%uUSycLgq6McWlo7|o~TEsaS#4@qKO zMUNZ_;XNKugP1=KFquyxeo3IbVACkUO5A18q_r5r$6@de)vb6G@}k&H-a}|N2GX|c z3Du2D)W^?*-`jLCDWwGKDa*yg<=DM9=Ox?y;b9RM7tjs8b^Y_53j#IUcWPx4w^EBF@k_a0p(b1ot}y@%Eao} zOui0S6TPKs1bSXhf6Xi+y-3{!n}O^RVQ?-1b+Qk#Ls3ksXr)oXFe2rQWZVah9Vs}kZ z@dBPjqplj=yMb)rR46sTdu_Ikf7WEtrriqBI)KVrSNyI)s34=IECA?~@v!jW57v9*Y$}YS!Gm0niR4l8)a3Szc?pM$9xE# zh<%2FEmVn`XO%vpJ}G%Vawzs^e{76QQ1bk(PzdY= zG7~8yPR1<0Mnb8>jsN}?Ww3or!}%w-n@NQIj|yFgBvdCAC+^~;M+u$*vA0HAJ-ViY zMPjy>&Kgp@{xMa^ipTF*`zXdHUe31Dj2L-@Qd^@S*J*(?y;mEt(#h0hd>Pu{T4+g4 zjg_*v5^+_5@E{!P6^APiQ({70J0gDcN~M-hhhn-8IQL($C%*k;v43a}^DhS3KBs8@IkHGr-Vyo(pu?5XCRb51peV;S< z!4(f0h9HY^^&UmaY<;sOOaDY``@jW>rxPxC=WWoyobaYX z(;DatV_Iq~MJ(KSS<7q_Fxph#;Dbfw*{^%>`~{^NboxW#9UazCZ-uyyQDuu`s2fGo zR7Pee4AL`75ynDxyIq_$?He{h!@13^aH?ntWB`AxX()FjFyR4c`*UoFEABIGfLPED zZ`eBhUzz*;(-=Mw!|fPKZ(JIqpaRgk`RdSRTdNouqN7{;Hx{?_&*lB@ml=aH;a*YI zlDQIGMGnb!p32{1&{Kp6uzy5n+c3P)$hHJ?g%F7z?egYX;cTE=S$qP&EXtU@-15Ya zs6oGA=jg62tu^}g9sy&f4ql5l^;ue9E6-D}vpx~Bd3UE%_VPk6q+>ri7Y}|d%kIVl zYh?}Ae6(@V;Hv^o#^Jboz}|3mNY=9+z{MywVi&M}a!vEZHu7(PdIQ&os(8+eWVbfQ?xLwsooc%7ue?-MV$Y{b8)V=K1+Q7|5-7r zRu)(MOT2$)5D}q=z{zjPFNFmS!@EKkgsFu@@P!{+nVJb4&?RQ1%ocmYSkqMv3KIBw?_PwP0DoWo3u ztv@|c96@Na&_D)+?!nU^E2bJ!2o>LBHO~iuZC@mP$wxXk6a8m`7B7~4FHDZ^@{H1o zDQ$00fJRfw0JUR(&DsF=nZe0cWd71sNX}UxWa#yAY5Q}j8yuqbR&!Ge>jRyGH4!6e zJ&>fsK5Pk@7OZ&@`V2A?<}FO$VN%YL0pX~WRK-djy!hm}LE1o0i<=~7mrT$>ojeIx z@Qf7+8XZD!KuI7PnW5Ur&8HuUbgl)bxn_vtDz2M*vmhiHCTuoX9O>&TLYN}FJ zHt_7RO#Fw!)x|&=1w+Um>pasC@|Z_!cp5iH#;p@cB}kq(kz=Cd#hU5_K8bn*MkniZ zyO8JgxJ_7_2MKPB!hEQGG@a_fXd9%5t{G3Mqomi+Z?a{m*7KJmyH+ddRFrb1?;1R` z>mP*kUTrT2l@x6p6>pBaV1dM152H#+G-4#fmCE;)GGwa?`(n~$_T`BnOHLiUZHFtD zgSG*?CU@bqwu%nnh80wsG6uSb8p==mP*8ucIl)}101rILQss+6<)}X_ScL8&Duqm~ zb5@VAT|gHAoN0~q|6|Udh-Ml z6^f4vqGgD(E8&O{Z8GYd(fP8s30^wYg%V6<2yEJ=61z}ej2bIw3x-Zjjz+ojzKLPa zMN!_vJ^e3ibtCmWh9x?+CRWrM$@N6R2_YWf?_e`O5bw9We2KRKF1=xr9z9W6EZF&) zy(PcWX27|5|Bnq=nza0YGk<@IY9a&x_?JJ+{-1lA{^R5Nw*_Uk2BeA} zS1X1}tBoe$b9k`{%4Iul#tbmG)GA^H%s9LbAiCJcowfoMU5Zf)rb_F3s1r;pGqq?fiQ(hb< zH}%a9k)7K$M9m1?`_d$c2t`HBQxVLLX>OB~V@Q#qj{)b>pR~C=8ON%nm~|PeIo1MQ zqTVUroBi!L@?qu8g=X-_tsdshrV4dR)&zI;Gcy_c(;v$CE255Hl#s^6h4Lc^-EsK{ zG0@oHlPJ~!s#jh#vBBf64bBQoB(e^C8iVD+%$|(od_1qE`n{W;5~)?1IX`HlBB;YE ziwYboLn+1CYcqnWmqDWB`Agb(4KCuFaPBYL`P$nh$gym(; zO-_Hgx)7A#0Xz+VktMT30iTJ~5{!CBJ?IO}{8X84dRK=Fc!`)TH5RzMs%n#2h=iyg zgpwgHOdhr%%)HKd$ewQ(S8~+?bI%VRI%)yYzlGVxx@Kptt@Q4`WTmAfMN&;UgV!R{ zFxdwih)rzvNdweuKc=cBO(MehcKR$p_UyGu;zD4NzB|?VSOa@?&tpU@j1kJ?-O${{ zmxv@C3%|s1s)lkP8Y0NHKyEQkq!3Ct_}u)S>})vWrlxVjD_^LJB1G}Pwk!$Hf-6s zB3FFSzzbSEO5=`7Q>Zgmf1s0n8sY(^1_IjFE5dvWzj27f6d&D$Iwi-hDvyWSXzCr9 zJ!?Gsqryy)eu8hZv!3Ux9vy;w)|Oio>4){?o|Dq(>aFv!ixxZ>MJbjIg=r5to1xOZ z^<5qIB{Sv+=d{rZSGcYDYfDV29hGttB7Z&wa^PmO^<)YQMwR;~!m_W3oiIw0u8WIR zIJav$Cx1r?{Q_{)K0jg_u|V=kK_E9T3DN z(rl!}j1IcC1Os4{>uJ7>KJR`rQZ=r2_mI}PE2g(VaL`0o&;qwwAH!;ECKF0{A@QJv zzSSqJlle1R?@v+C`75i_XSG0MfgV+NMb%SDOz)tq83`dAnkuB?pUv_acga!SvI_xz z)3Jzj44({zRebAxDv$o9M1ppfoi`V3eDvgGQj=P(p*yktF%4J`jPmrJdJznQe zlwL%oXy$Nz(k_`rje5Oaia+S~f=H(k8r|g~ZuZv-S8lD#P1y){p4dOpKlnX#IE{_n zdI(cujT7@8-?kG&S+*MqAuz1pvU2tP5ut!GIS*DLMil6u@$&~?Q(GDV8=e7eUxR>{^YWBXl@GZ(=qv8if6A;UC-gyUt%hK)dQDm|_(ifWb z$oehZI`HF*M7pS{NKxG?P(xOYtn))s^Ig|yw0Djvl`6JX{HqIFgYnDQQxh;OK2vZ;)RQY@L?B4)i1c`aq)Ul^qd z)=2K2bSO&6ES5<0wnjNL56X)ZnPC20LP|?Rvs$>!xRaXF_Y_4eR13!SRQUIsD*G-; zJ<|!T8RZWXfa(=a+9YYpJTB21_Rj4z$O__%nfjW0WqqtA{AN(2p3{fUbz&99!6eKb zS%r9cOq9sB>sE*?n(~eGM$ZYBQr4QqlkFASWC~XT4*ZA|nk@XCA`lF_$; ziXxKrHj`}9*waoa&2e{^-=iQ8KR&vIz08 z?-A6-l$c*M0IbzyrLm~k!EQCErpoA}KQc4vX!UltTgw93@@{6V*xFidEHs!}dT)xf zbgr{N8YK3KkEk}0dr@begVrB06)p?q!GuhwxZUV5Zj?|&or@!HwP4QYdC1Ci zC@JGB$pF8mnU=3bufr^PZ{3KhPaigW5}wg=y!~2!lfA(DD6Tm+%n^EG#2mSrhfCDE zEKWxpX{&V~h$zQI-?>pUL`bd2!o4;LCh^Iw_*&#mxN{2C-$47b1ggFqYVJRDmCOUl z=DL=CU|Sh9TTg=%Rfv*;Fjv(>vE#)iq~QH9{k({(m5D{9eY32tk|)BVx*jhQJ*G}TR)9c7&s*< zN^jfLs0hdw^T+HdLBw?gvr4DM!fCUkK57J)%RKNxOv!9msagsw|&pLd4FDp(f<9BiLF|$)BLl=PAcKn;azUIUTm;_?5ufo|Ujc?{8z=CEmtt$6@sH#D}bS4$fTDYt)=FnVH`3 z1Sz1yzzO~&o8#H^i`PcI=*Zqkkore3rd9d2`&A?*u1NK)sw(P7|fiWtfBa0S#xIbFL73MTZXpHi`~uG5c}@1a0to8;p(nmA2#Pt$O-qBXl>F zVn`n?$L-SSU8qpuTXM<1CB%y<;p&lNOtBR>sbbX^9^%zh_}r1wc0IqP_%D_kOI)#? zm_<(YS_kg_MNca496}xCb6OXC!TJQ>j2UiV;5k5-o|Zj^i804iDe8`ncV!>AqQl;5D z-qbPX-~pxL0&tEC&d!NDmOKi-EbTqloev(>%LPJ+yvlRe3$Z(&JS0mH`ch1ffhP}7 z$Kl&StMP@qlxP()03Lw(i{3D+IusongB><4SZw%_v}{nUs=pY=rr(vNFmZ;?S`a~- z(Qm>Yy=4zWi!q4JI~K+6uHxCrdDrIR&!t!EpM_{!9ZJ$wY7_6AaKFX7tL+%NwP@S5 zK)m+skH5cH$;IpR@kAx`1XT1wY54_pd_x1}igpIwc|)*HO?*8@0r5ec^QthV1-Zo1 zL~Q!O`OXOiJ9#V2dKa)XhqAD(W->4a;xY_Lu_x$?&|KJpKWT?&?(s`D*ZkP->gtvarqw252h4{;~nT2 zL*MGi+TwEc>`tBT0KxakV=l!MR5YOetu#fX(V^^AKMh$F)uG0_t^ zm?$4MMe2H>Pj76t+e0$`ytUn)(ng=5Agvebs}0KqB1&?ry7e$!?r1Gl_Nk zQF%$<&{yf!w40N);CZob*MbrUMc&CITn0M{Q@)5gZY7_yUl`AMkVg7KGNR~S%t_*^ z5Xj@q%d4P&*APoZQMQ(cjuaPFSc!|q$qfg4G6vH0ZR}oAU>(-Ccw2 z$^hJ_#D$~Qy6?f zOO8D}y%>DxPh;poVgxRQC1aM|p7IAck3IP$fn2h28cXhvsU%qL zV?? z+5gd%f|bwZ{;_K;p|$SRwS{i>BXDdMHTk`>jxpp%xP~^6!8VV>=cFQ~kzE$*w zVNf(IfZr9yoUw&gp}3vN;!J(%zRt>e`8Xb-2ZE1NM-)^Mlo5va!~}PH;bXVlY>s}c z)>VAO^t}HbQ)Vy=(yb}|Igp@KU?t6AlyjP3w|AFt0gEr)_R%0?*sz4K3yn5}m`U^F z!*?Cc{k?3+CnJ6Vg0RA~UwaLF>^_R*Pv4y z$K%UUSLHs`Jd_w~6d()GHbJbk1JPv@;yrw^drxV3Om+0)>a3;_ao9KU07RMAr z8S*Lhawz6d{oFw+-p3;RcitZbxOUSKYSZB$&14p;*ziTzON1(Z(n_NjHo*p3zwHeM zTG!Z&K19X1zHGN7M7wQ@!C9^D!h^L>ci+-}4W-n!0{ezc_#*j9kpU(xhC0IQk(O}h zt{O|!d7<)7D_olVW}`2y=YR#XWa^7XC`Jm`ZKE@&Rm7;8{nGD`P(uF9oyViHKf9a+ zd|MIR{)=Vx?~IDW%drX#mjLGm(RLJqJvv(JAhm1&kA`N)(1~29+%b{|xTaW(*)8`f zp)L`MP#U0%uoLxXZVp z7j#LUD7qYOQ;}zoxFL2xD}^k8ycCpv9rP8k=4@qJxV5MP@QeAO)Rf!ckGQ$qS`*S;WeN4u4(X085gh^<5)?sf*|-5Rj0jR9B^=V2Ik6a#m5+>mY*=cf zILGUX^GoyU<{28E7iO2JekL5}57nr0J;V#}(9dRvYPPaqajQ-^oW+k40bd^i90oV& zKPl=D+!D$c0_66xRC*eoSX7j&c2-i30C0bb%TNO({*pKJeeIlXIYsJMXph zH-Sxo-CQo;3ODLJe8)ny+ABdNrR1Se(B=D;`hrdFT9!z(T&_XS>Y5h9dpam)tyHHe z%1H&fZ0aJ^$;ef)uVZg)gNRxi%d}QP&IMg~C!{DUi(LsZ2(``inRB z;joa`t{#Ok=kI*eqR`ZvLj%O8z6V;QZlJ67x5a*PF+lKJS9J`LR_iwP5sCacWqM%G zVQwyx0b(;KY0l%l8jg06c$%kc-~>Ks+#eSp=bus4*=$)~AF^A92%Ba^2(Dv5LQq&L zY??z2%4VWVQN4f=d72L*xD}z78=;r(9zoOHorY(_D%63zb&^VT?O1?GAFm$>Tz_|A zn$7F3>so>-i*Ar!m}e690dre*5j`o)m%$F$4AY07L}@ADNaKCs@YUNZ;{< zWHpKF53^y8e)sf5bX<2zgNXke`sZLqD-I%$t0r$APR`2h{y$#tKTGaK0GXJ84a0(fVtRC=_DV*XV|S}O3F z37(-5+@#HMD(P9=&2e<6=Q!@TR^zIyKbud$f9lD{pb&F9z}TtWkfGWQYagjePk;kk zs>Fh__G}}C4WA6)9;XN$Cl=A!DLceI4DAQ4`S^nfR{m&1zgD=BL%r_r1WTE$v4OIz zPqSfMA20fX{A)^V>|$_kdgdDS65Rf5Zo>ti{ixR^-}k2K4TO)P(a6xbg~ft7&@mGx z{vk4S=Ak_~t@Ipv0|3KU{4RJ=CQR6cmx-|{_<2D`TKmE z@{y%-OiZ$cwWT)O4QyilrJ!oX3EtuZC9Z>BgSFb4f_*`~iv;kEmt19CaXyUW zgVkKIY(n~9X^1>c)L5Twq+D zoL#)UJU6HR99&)*7CVK>MyYACS^Qf2a2Xc< z`CwlAkjCRDGx(v!LNEepn8S%iuu0w6nta-`u{frkuX-lU%+~RdwNeG`BN<|W#g^a- zLKic2{zr=WE2CE#SFT6PYx<*vW>+ReTn3T*Xi&>>xZ7g272Uri`0diE9oS)~`12tX zWMlj5sYYcw>w@j+fel z7)X^h3&N$sp*as!2hCwerqJ!=j_|@9*ZN=X&g(Y$(YYq45Y_SL4nJ^4e?03@s)a8h z?0d&J-mr|waK6(aTbZ8r_uZ~1IS`IqCEbGI)JkL49=i*VyAzLODh+4u1;zE`Cn(8D z(TY#*YWztLYMU`E-(}t*N`Z#Yt(YR95=GqsE6`eui;NWg0hJermKiXw$2la^J2F2_ znbpc{heZueUO(S#34EM-c+2PyT~Y^t%E^u#NAoDL-vgzq$myT1puE^l*H5`l7rWnO z(E``4Ht|SY<&K7fI>``w+C}jsn`006x6qMXS4D2~R9lKv95my-tBX9l7&g2Rgv8nv zM3!HP!ZqKsrpB5JA$0EF<&LmDH?MAaEl|@Lb;CP`It3BRP=BL+AJ1pOC4C<+p0rYw zl0K3wH>_M0qh>RVY?H7y1N*(IML$T|bggFH2s`NINcRPlS(>lt@av5wP<#ChqPO;E%k>v3tvxL3 zUIi!yHm$!u*s1fO{+hZ#s?a`W4N`-d;y02vA-WQX&MHkjE6pYp<&jyaV4~njc}Al+ zqDv23>AK19!jj)EXL$gND}knvf}u%8klxIRynE=zKz8{6U#IupLVA1eIH1gN!o#V_ z8QwLW6TbdgKz^R&)gTRjI)JXBKh74KHmDh453ZHl&n&eVw9Bq*(F8`v6R0T`fo%m2 z*d!7e2yVwD42JM9{KF-JELx96HVzrh%aQPKj8xMjbFo(zgt$zAMd`sxWu0M8^c$j` z7YdJq_)Gg>(G!Yp$nj0a@Mm=qkV!QPo)P=^p)M_uM-Cnc&Se}Zj#n4C2VKTgs~EynKiCCS_{pP5SiZPcp z-IJ!3L8>P;#?lZlPtKTJ9@c18ee5sPn7iiM$zvxVJ%PAb_-y8k;Z>vms1 z<+@Q+zr0*gO+YFc`L-XpsuUL#fKZVK`e5VAEL&pjI&e|)NedRa8_1u>U*T?s6k+ou z=-rNQ_C1emr?+=}K4SM$U%1;VI4b^C6ilAwKu0GE6J>(h4n1ZXhg>2~E_+W?ux$Rx zN|S%oe_s!id&9L5CQKR@$IbX`fQb zLf9rO=Ou-_{HDgDXklMsXi*+2X1*l8Rkk`$Zz;8Ehq{CYxcrg7DI1!ga9t^qGfkGi zmD30<1tAcX82dknJDsqWZxQO^E#%pl0^mll-J9Yd zS2G)>j(=|2u}@W^McE8+wl|ndtkRIwZj#PGjl#85`9#_L#mlALgUreQ`!5D9oiqVU z;%_d_&OgS}|L^nvPalbzruv2$$|pEBNtDJuNlB4~bYc<)wta$WuyqhAhY2*eQbLK! zFfjFM0`ZtY$MsuA&1u5bB{gs9P(G*4&YSuxx~He7xKdP~tNi>=3$a44p0_QNtI6E2 z_g8MekLSKnD0fhIQk8;;{Jn%O0&%4VHgwEzeI-+xkcz^J60H$Tp1$QV%dj%E-9!bD z@O)ABBO*t!97(G9rmj5mcv0bLV-#X0D(x}b1(o^RBtwS9^{M?tQjE7Bbit|W$_)~WXJSES$}HONK-0Q(xy-d)__-IU+^Wo*)I_}mz5b`Xe9xe16g!p^Bd zKWF=QorFboFar*8Y1wd+W+N2p0d&0x5Gg8Eg4pX|&Jtk;@PR!VL4ph@%JQ@bZwhrN zVwz%aBs`gS!{kC>dQCzbHx_DR>Z zMlgE`#?o92W6btK{gQfBz;jq}Q$>Et=WON3zwkZh$n*63EnpPtBKKt0yFvSARll!J zTkd?bn>ar~NMQ`qI4E|Qz%&wHUQeNVZqdb1#Vk|?GQtpt5Lqj-f{fzH+Y$w%Q;_il zqj-Q7gH{2Is0>pb9Dc`bT@Ym!d2^DrmLhFFP4uK=Gtxz&&L<)y`YnZUb9!`UO}qeu z);QGD1tTOAJq+HN_GxZ>+^%Y$mni>`|FudtA2lFmA|mCAAWWg062?XTFRZ-$;OlV7 zPqC0!j&Ki1%A)c}s?E$X(&g5dODyP8ol{>CxP5v^=aeFpg^(cpQ zHk!}_ZdWBXmCs8$&*~znHK>&9-g8%8M01+0(9!spF9FJhkuSU2J^wV#Uo>J@vmD8K zJillnAc5UVfOFT${dfz>Bpa*Z_ie)Wlj}Dew_cT#mRYse5@*X_7%Y*S8Kra5@e`PB z^K9xMiA4(>-dOI29;z4%Z!X2!HIMCn{wy6vUSctnwdqx%5YLP#5D3kdc*5!xE`6+Y zhlQzKPzOtR_z>%B6@%9`Hm94%+VVU3AoCG5H)c@_aWvpxE3ljE9M{_nZ#|{u1a|*< zJwKYfSQ z%SK#&KAgXwAy<_0UKik=%NTDL1bF0D$OxmMZZ`?Z2LuTU6`XXd~KT2DZF?0x+Hwg&%I)6uS)t)r$PDVyHw{mMA8eqm-3=e zM$A*~!&K&7HqB-B0oy^*`W|`;xALPuQ4J+ZKfWdgd7okp&dwmDd}Q1&?apla?X7Ef zhYyu!wlO6SAb*mp->{7FT>i?@qjqNuP5m5w!^^t}po3aU`rwLE)E%sYMh2_$ysz@S zZN~k1#p_VMA@$W$|M7yhvxW#zi6-h6f9(0^Wd5LCzH}t%2;hncED^M5O(Zl9D@aXLLsGE*NP`6}t`aq45=_YC z$njTiwokGfmTr6<4_O3L!t-GA%b-^(BYE zlZv1d>XfGH=JzcsuDEN4+v)Qxkpm@_msrs)>qLaAqlz_#74&IZWBDjUuvl3q3s2h& zA%F);S_JAh;|z!2#erL$_MdQ46lUsp@b}{K$=d-HJcmNr5DoPtqkSYRcY@!DykV*k zQmovIl>`fBV=Ns>h6`;K1`i`&`4rJCU~XSTvBW6Ww#YuTm1Kya1vRyK<})GYWvMoC zvB*(5A52PcFOHhhwjdYIAJjg?jKaAp!v~weYMa!Buz3CI;UYq(#`C-7DD?I^ReR_j zw)D>It8QGA)xwe|#u~}$SaMb+8M|QK_yZ9Y|r?F=Cbk1hzWiAlNt~y1TwKu== zPgCatvti_vXPCS>T0ov6!PlpDX_0qq7|??2)WzuW2+(zyqstLWeYI1Z0Lk?6 z?@OzpKS?iA=VC)C!bNrFRb_1{N^BWe&`$r(EQ|>NfglAifin&&s8jV53?-?=<+4@t z@zbz`m;^BhiB@R-*)N;{p#ZR`lc(@zfK~hKQ>eOw8X>_=a0C>>U^^3^DJMvA4EsPH zqO5o)hDem}LCY4)Z-BS95P@k~|Tg61UMBt@0p$|&9{)JVjFLk`3+{dPFE zO(*BP#TiQ08r_?#X`!nX@BIvjLcc{K#9l_0v`X8_cbOOET`E>e>|$o{zy?qC}g zHl6NhHRo+*XyPVa=as56PLr*&yyKkvZ11%TGvnTWQE1uLF5!AXB0BvOv zrZ&s{?NVSAvrw1x@+_NsGI_n98#izEGV7&VC;_gWT>&6!-%$A+Rsrb^oHwcM!FEY1 z73nB~VEAEcTjIpnn=U64K)A*KtDDwQ{ho%c9_-fzu?=SG^j?sU}=j}?Px^o>~m}BittLH zPd~*}{Q4JTJQ_6i=KXhl0ela(!Jf4P%!ClqQ=B z6s24hQBbpz*m0qg0 zT7@q&B**WeoO0pPzb!}O70i{-%bYyd?vReRHNycLB)54T9V`U(i(cD^fsTX>-!b?ygj7>#0jbDR|4}f*=GQWp_DT4Z=1v;JK$j>bArd=`6{)n!Kx=2-#Z^eR@Mc^);Y#D3~ zp@^=XwEl6)<`?ik*JsdSb!@_K;k@@dqxo+kssAZa3ftM5T9~;w0{&|Qkesxk_B|7Z zd=dKfsRCs>L2@ccMJ?nZ$;m=C0cY+Hufp*uY?5680ViRFn~c?+Fh3StQc-LEJ^^{i z?`RN5ilH4w|6M2UWs2YZVm9;swzKmE^qoEjIPc0qWJ7h#PBGl1=-W4sPa(5<-Kg<9 zV|3_alHFjCe6 z83qPp)TB(QygIe$Qa7v3PkC+l^(jpq*N-L`P&Q%nIN$`yh{uO8A5$or@<=Hw3X^;fCo3DchsSB4y@*Xb3%@tpfBMzw`Dp`{8p$V zV}fJ%I+A~BEI#zk?jWC^w@EfG8MIH;N@BC%BGs!-)Cu%Yyzk;-uO`;IkjE~`DbK|{ zX$CF@K|Iq6?b6z36<+-`E_Je8g|U47r5md{KUUYAa%6w4l|E{-1zF=fJl+_z?1t>L z5cdJQGYqqpArk2hQopA5(p9HcDp9p0u7V9ybmwVJLDuf|$9f{Gm|Z48D~o?XBCx5r z)0X^cQ{0HjE}l>3bV9E*9>9*h9g*6re;ZW~q@+wAy=Ifz?@_78z1Rvf2Yt{`n1dYU zE<(E@7;Bfdo$SH`KEQ75l9zg6mw5sCIyZ6P%YP%@fp{g+x{Z69(S8tMNB{OW!%Cb2 z{rA~JZM=)l zk32Tep36QVI76^k5OZ*vyKdh6MuTK!ggO)?iG}fMzZ+kORH4Rs#8>dx4whu+*4RtQ zZjIOto09Jhmk0D^#{n|v8zSY!G@asPLndJG{*F0}K0lA*{Wpp+3&foc)SVI>6Beju zVcH`b!8b4(iyJ8}c?X0b1BE2;f;NtPMFTQ`gwnJUHtd8{kt0+cDeja&LJF!OvJ1wT z3!*`oF`bQo*>-^$MIp&=5=>A}Qc!9&(f|9e2oz;Y5F*<|iuXX3_!olFZWLqvno)0r zKdeJt79b6~)JiE-4H%$%N^$sy5j5a}&JmopAPpDPcZn+TO9WwrU>>yU#;g#IVvMHP zajg3B?6xw8Apd;h3@w?g&wWn=xZlnQx_@_5|L2V(>TY7>@_*rc$r?Wmun$o`eYK~@ z#!bdJ0vS*sL|QH|gd~3a3_#`{6v5MI2}JJwy=rzGMgw_jOfK-Vn6}W1omMv~1x*T* zwqXHcfs0+b~a(t#TH9-3VRf0gjU+ODcb?PKxhW_F{BVwlN;uwG;cV;XZ8aIKua7_ zXlJMy1IcM()VEeP7>ji>01ryRMX8HR$u%`5#9k3Gu?$$+12HswR*cj=axl7RJmFEg73VMB;dA+aPChS zVyT&r4=?Y>!>=aq@}*c-C|SKQ;l_CAaIAb*a+BpCu|%BtfH+FBs-@Yu)IIZs#y2IW zK{$c{GT14u<$_}4Em)EP#uOQOjF$etH#)3G;J)fjIwE}N5pH1iIC9B#HOghRNqjKg z7?G@5({()xA$F2v!&SG|>-Hd>c#&4=tY#-1$YzRPh-RApTs)e}et#Rfr(} z>!?YS`HCsA5mf4T00_glIx5vM-USPz2II(5r_2a~8}%r0lG(JU|C_t(tARpk(vF9I z+NQx&O2@2@%pWrGfUXXmoNvS~c64^#zcz0#I*LTX;u00U=gWOch1iRyfkn4ekABO! zOXxhAU>TukUTtt(gASQm;4CDLRNh|FAw^#aA%!&96yV#Q9D(>eh^=!M9b(7S)O59`M=ndiU}@AxxrL>%HmJ7Mj)3}m~3lSTE%@xmD7 z&*K%S6knCP2eRN{;#AeI9B0SzRoPuMzYh-Er1_D#=CV@c^Wnebh#_5=@vj zq{F0Fg?Out#3at4y^JWG2C*8&+D6biW==Us60EGHn%>(&9Xr4~-C&+v9{$2Sh>CW; zIeQC6p-yliB|1L)D2{+UBW++(FEGX*u;>#jJkdgeNm=0GlNq@9ZAJs-0{MVs6azomuU zS-wqEnYj(+T`U;8bx7pcZA3DX3?qJ@(taI zJU}iy>dvVjNXji7#1{?cAB!1xBz}&J>EVh$wBR>f^?lEt!=&ZJJ-7%%vbsQUTfN8; zR_YmU!<526M#>hymB;-;N_{Pfau$l>T#EhGcr>vpLBvZNx=xGr$zD2i0WdJro-}je z2|W&ng>R6Y%E}TX54Y$!fEL5vj5Vx`{ zu8C0`!7D%fqX|&H=N1z2(+JV7qx7w{@Ga90eMcQ0il=-*`19YA z?JVwGvjk^<7%yl$v1ttOqAxC)l<>0m?R=Vq>o?%PGK>Vs*-I{MU9!^9hF&9s~VsnYWwQmuP1;!}*o*fT4xQ$=rZgIO{+HB~0* zO=?jCR5`u?p!<5EYBh4f@%n?}818ELh8m#MM4kecEh=Y=X z+aEERk;5xQ6zWdCKM%(*yF7M|y?$6OX)X0C;?ZRH-GOL$K#ag{1uNVb z@9;vvtFjN9&T>R6UpbMaL{zwnfbAVPLHn%67`cD&BOarM^G-F3XVbmq%l-M*7<6CG z2o9ld6O-(*(rd}@VciZ)qGjC*n;9M1*+g}QT5x)e;!7~CZQg0rOXt#sQ|~dm1oSuu zOX`V3b+0x_uQn&(1AcO%j}kKl-r|sLK2B^tMhP>YPG7nm*Q5#GOSyei>@H3JU1=Y% zy6%7E>`GQt7}jupwqJwCl9#Gp2VDp26LxEczT-6;OU>9Dc}%c9^#uEkSal%0GUI*% zr6W7ez6f;NlWz&x{@TCCK-PxUzHYdk%yY{?3$ZmW~}*yQ6~Tk#7eH(^1IXfEmb+{O(HG!|8+#;)JQoSq%fJwCcRIiD+Wd>i}JukW{l3~p|Z zJoVvzjqc5Cu^*)IH1@>DUrgV>jSz0~{h^JBGj#)C$!{a3(}vqF-g1gr4Qqmz|VV~Cn-`LZw>;M9I` z(889mlL8Mq9mm;?9#J3NS6Xt5&saxOr;e`rBBXAQ*yH!UG;{C-)GloxkC^sy4U=;k z!E%U#(TT9rompRyxg+@G^{Lr?gxZ~zu`>x(E<}r_G^5pV1)4S3dcIo>*JIV@NxM>8 z7`~DRw!)1Se3GM;Rn=1FIzn0M9!8~~uu`L}wd<8*tfyoZ(N2b#$-_k!n6hpk-$Smr_85v_EsBbl6L73MenRiv$Yjc2r?4!pLzet!PrfhtC7T9A` zvFhDH+tpF%>B?vmS9kk+(+kOCM{vv5xKL-cpA`vRSlN@vsQM&jEYMMWT%eZNpFX!ws;YmA(Q?QCqm)e;#CTa)kgjO#bu{Qu}C*{T5f z1qBq|SQqCc!Y~NrA3sn#8Wa%}0ErR`ND1L2G}7;;>Sq*d>&52+pFurfJy9aa-z4*K zcYW=V)#255f$Q@vpW`gAZJ&pyT>KuODkE(nd?BKsZ-kT?2ItZ=OLLhf*rUa7n=@i#=T8cv%C+a{v z0TBrRK@m|{adUuSz*Iae+k41`Wy{8I{Tuu|-~by65NNHYH_bo8fU$BcVP`CN|HfzH z4^iMT1WoWv)RCLjaPN>~(dx4(-A?b~?K^;oM!3B&L^#MWgmuuT?``1{X*=wvA35FR z;fpeckH7?`ICR^o>P*c`zNL9fzp$t?4aA+N_n_9o28U^eEZJV#aR>lb_{g>fczhIS z4`InCE=@6}Ry))tEn>!Y0*iKY(ojQGj`6snWg-CYWOt%3_^%sZp|WO;m!B4Nd6=M6jy&BM*P25(INi)rtCh#<=H6uQ%39X(6xEgGM)v2+G3oGU*m^?V z^*XMy$9-f0Yq7ZtYt?GIm&+Vv18N|PMUVCqXx)A{p z4;FdHIKM9yjCm?`{C!GAA?_b8o)Qw>rDn?X{mk6u9QMRa|Mw?;>bQNF}vz{Su z7f`|ZD8jKwNb6MwBw&qFT>`xH)=-Gjh7nA83N(LN2@I+`P=Mn1F{H%h!EwBBi1t|4 z>m?Uem}o(xs8-Eaz|->pkp1g~BfN8qXee0+Ez>%zEnT-4b_=ClV3G1`=dM?5q<=Uu z?{ti`BHs8EQYb`$iQ!O4+KMD#$G7!ean}pz(j_1_lnUKGEvpU!lRux4>LF@_66cT; z%BNrJR9#8Z+zi(Kl6{=AWC!#Ag%EBSm;Q#Qv{4Vw)w`ip}p`C+#<$UGo3; zc($G6_^kye>v9knUhfNLnJJOj-^(fLD=aG?_q= zmJ+S#OIMV|Ene<>6K!Va5a>OLj&1h)Lkzgw zAO1lr#t)9`bZmK3Lg_oFcj8q5MmGGN^T1;Rp)lft1q=f8Hxl$cYi!>lbF3JP4GV8!?S{R}s z2f3}5>DYaFe}P~hN0<7xPSpU#4%V#58jK`lN8p#fd_wdbeFH*O4a=r;XzieN(GqI#DM=PLl!E+bdOOyH<^Y+9Slvn=26|7qM592? z<~JtPWK%pjsEzlNPH|H~##3@Kkz{}caVbh;MEPwqHOd8RG!l&mOH|^cA=9=@PWAUY zN|F`gF}G6-Jjn4hk24J$5}|TluPox5Ql!0@)p^t{AkSJpvt+*spQLO_-3_rsh@=t6 zu+L(Yo5wC2%C%CI#|5t`r2^JN`?=6s*neUa-RY6Imz_K1-P@PBjd$+haTf+wV``7t z%tETiCT&iav%V9##&mMv^mf0|u5-`aJn%2~LS}PVSvQ&mxydjWoX=HR)?#{a)h4M> z;YSpCG%#7Kcqf`U#&T1bL`9@4Uz_vP%_Szk60DHwfcNm<^_VjF1{NI~X$@Hv*}{GG zGS^*OIKn~kX5s+g)lMi^*a$*-2q4~tPNHzHRwu;Q3k{c4wMw@5u-*zka|!8Qz$;X` zq=8{=(y0O(>#6i|qUY|EP*c&Ls=*0o@1Z*Eldlwf9?snm9+sPy5I7ovmq*pm*H57G z=Pdl)T(R080a%>-z49m8o+0ermG@MRy_J5IPFrh@f=p+x#?j|5Q~8h@F^=!5L6z?J zoMIS9=52j9un8<4nR{S^konpWa_aFoPoeMfbBKi|XPn#jfLrZ{*>Utc^;_RoggfZi z%I8_1#~FCW7&-e{-GW$*6TW$ILCiq}u@gBa(HYXHJ;Y($#lj#91Vt3Z0!{pC7YsP7 z39kzpLP zQwzC%#dBHC8u-gRpC}u@8zydXytoop*svaf?oeSNi$sn1n_u_tskG)M-0@ddqys5twJlgu=>QOfV14t1LvL+x=Yv-lOr4cJ)pA0id;<7X8JfjKMZ(MsUB7ak zp1PUu|F;N-6iRAMU`DJj_5-bN4mp$QjQMnKM1_oKw{?at770-b_*_dO-Wk%ebh@=B zmxA#3^xAA58*Hh>tX82$I1Cw8R(<@8OL{bIK&665lIUc%JysoMs&k13ii4=G{;VDb zs7wql;Y;-0yx)YeNtHJ}j#EH{B!5v~Sf#%pvP$->$!8oT;N65FS4Ko;*5PxjUfAF# zPfU91Y9>IU<->g>|4VLVB6k(G$eA(uXhf19^E?bP8r!W3=1g zFOq4M4~{YMa>Lmx`9E*kt*w$lCBF}=^ShyB|DWpJe><#yX(E%Awxk9aQ25d}&W?88 zN7zs3SR$Z0V*F*m^7CdJ-m18lqu6LQ)qU9LzjH-WlS*j=U|XJvf4o0@T>>(~?(e~gTs$)UR{eLmN4`+Y(^%uSB?_~j_e z5jnD2GLS!Nnl~!zBWjrtB#jGIJ;w-@cz@HAyFAag@*X1l|S~J%y;%KuGB( z17kGdx~RTU8n_17`1<;ANiikjSj;JkLPY5V{(jQdAZa*BDmKwFsba_7IR5yG_b3&r zKaXX!(JdABbscYyUOR8w%Ln|QABXBd$2Tqryf>6Ll_#S312-jqHKegJG-c?H*gUoY zCz@EUB4N{&y}DW|7WF0 zJ=T7`fP=b1RJ0Gt^5$yzYN>q!YqLZN3Avv@UtOcX+^$A#KdIAq0<{J<_m?T$&PD8FXb`Pd10m*HYjh zI5IAQM1`~}S6#s6sD}i9M=6^6@Y19K7%6?xPC_`*5IRU&oe)d|0I{KK12#=l(awa- zo>oAlj=hk}RB1|&d$3+%+W4}CfS-{DH)3uK+EYV#wTg3o&m|ts!dSKfJ@JeHu+Hdu zo2INid*vQOl^kst2prB(-X)EJH39f_(rsCI!ygz_x78zeX})T+CUJ|terDul`v5Mq z4Jr;yo2KJ|!3?`k`u<+Cw)TKu3<;U5qBaP|> z<&D3RN-D2d1JC<*>%x&Y@}KN0(&Cp8#_iDG>OE!`GRmYUT^d>si`O2DM-2)Z`-}Gk zI)>9HGeKkqlS+r@RQw|R^4K*?k{mX4%9vf*3=f$N)$5(@llpihqw}^`XUt)S8LwIT zsiDrL%>JZp&H_m!XQsG<`{13My^7vzsHc&9HCK)Z)r@2gW`dfi&T~bO2JgC+S3pL= zK|e%#NuW*rUF0Mcf8>Kp|DBig7`bgHPN|wi_4CX3J38tO3t`yAcuX+`B^sOE3oYb? z-rHor)!}bR%ISJ1(1ITaFsHxT?6Tk<>w3A9dx!qcY97{^Wtu9CX()3}SD)ui#Wsn_ zfCsY)#IFkK*75`nqJlz|JDv4ne9lJb@@^ONdL(Xq25QYa6xJ3w|8erXCC^+wec<%E znfGA-LZJG>7(0`Eu*FCF2JhDlCDPHy?f)26Wt+Ic0yT5Y*kv6++2bW-dx8kVspxQf zUycFV9R_^!&hColiv?eGPOp8~J@@1Lsbl zmeVO=DcxuO{P(GS_C87P6cIp8n;0J)0v5O zqV)!{k~htwxCOut2=Orq^CFh>2em~dl#E`MhD9udJ!W!Aw`pu)I`P?kyV4A@MUAqo znN~1LjvR%Zk>V_Gz_(ttKO|u+eC({n@q~1fu}vn!bB^Rukpf6+CWR;U#(p0bce3zA5p+-#<{Oz{{Bg%|JMQ5e+koa`VNl&%i13Vol`+WbaQ7 znVUavrmWP7Q;3c86$>QnPVRt8a#cm1P9?;d!zV9b$}XXB1f6}C+(yk-MA<8m%BQ;x z#;ruU!lbr#{iJGPBK14omuDIQz7cY^8hTUE+J{OWY+&ycc4t!d9N6x?FnDk_*Y*P;k%T@cOO3b;pXfG8OU#rfv1|DLM= zs`*9(eptltPp8dMC&^k(+J!M)_=E5Z;QJ5uX;)U|6^DMQ+w~D>)s7lu<>#h$tKJ#o>E}FSKSsr9)0!KP z*QObn7#01eCoo2|COUxl=zQ(!#8JpQ`_Hr*CKyA1OM3hgCPLbqhusHxb|>2dw7BF|7&4bOS3i({a}YZsTiVolPCp$v!d}y}6!s6q!Bj-W5u% zUcSjFAX5_#4d=teKM797M?+mCjinrm082fcFH4?sxV zJ;L6SdxcBem`}Uc6t*B)r%O|y7|;1?k=)~DgJi=A$FT<^WKGxDLE9avk8thth%!HP z{#~)b?cd`AOm!IJ8G7ZoN%XUq*|lNwDa$%2LP_6;=ZBB4ovjX{=f1jJ{zl|0ySDLj zkx`vPO_)BFP3Hwt34o%Dw&gSP?=WNUqOBlly%r}<5O50#W z&N==FrtVb0+smGDT$0H(Ko^%0u}Vtk(^K1uYtQAUOV>#MO-TY{XF(}C^{(z79)pX$ z^N^Ip+4G=c6J4B*N4W<;!vNL!7FiB7 zRO$;3yw)mpMt6YD08)hZh{tmcqJ^)ze)@}m_BZ-m(Sb+|<$e$);5d-lS~>07-;+gT zj-|i4*6U=ul2fXuEWN6G%tiY4I^rZRXyUsZMQ(WH8&YX%^Ca{AR_^2#iZ*HYAg{<% z&2dM#{~hT&uF|31KgAv0j{wd8Z`2I`73u#lRL6f1UYKP0a|RYEc)Ol@vyQqU2X7A= z8CkDeuG97YGSR}S2%BQ?2#1;Efm$n*sAK1>Dn zQo)C8yZ2)D>J^ZkBo$>m*BnL4)PcyTEG)mtbG`4kMxXWr!~KY44F1xg$k60UDpAC+ zYKtZaSw{_fzYpj&2!+b5Bl~2=>C{_33irF?qgYyD-}MTcR46cN^M-1TStSX>>SEJS|JDELB*4 zD$_M@lSId{0}(nYzhqkxlBKi1jvx;81A?t}bRH!{krqwFeKoNgGEfB`D2_8^oTiyE zMFxj|=(}$Y=?`3;rGg1b4ic$m*6e`;f-b@#H-kOLq|pRsv0yrAvFv-L+gXgSjdsE` z-8lCpDRQOl#`akg2(HU9u2zfL+{*Qu`?wJHWkH_gu+E%NPt{a*vtygu!`yfvNPgh< zx#M~SXtGO&d0EvS_~*F(4xTe0Yxxs_V~CdQHN^O|vl#p4_i%1?1R1BGe_hPY*AEE8 zT-@}B9GA>9xwY8t8$!hELC|+Pt-z!^m$qIoQI*CF-ChG+Y*E9gQe0-7E&8oP^e!za zoMF{^W(g;#8UVtOS_TT8)~YUfP+4}CdD;<*qZ$1=!vSp=FIyJ|Q9i00>?Jw+J}7=4 z4t9^ExjBFBU(i8cDyqivqac_6D9953J~{-9O>7;E|GyHUDyA@!kByod7^F14o_sA* zE*}69LcCazV97%h|q{5r%$4+;ND7O;3MfW4tcL=XwjH}B$f<(Ag z*>MZ5iRslwtLv3xc4}+)_v3x_uc5!tgn<~?X?_|D@F-TK>2RKX8;N25Ze*1MeuPg? zKTPw!b)Z9=49wD$*mM+n7pZWboAi1$T5F75n6=6V5&Sdz?rfMaVh$!F&r*?&pl0U|!yLeCgfy861dF;kVl8S>L+|%4rp@Ev zF<}l4K%fJ`>YWpY8=STnK}^-$C=gg{$zkQb$v@()hTJt5faBXT=-EGpfKU&FB4$i6 z$)ALavbd>q9&|Y=%wjKH2=xGKkYnw2C1raR(Lnki9gwD(7e4$NS9^qt9yv>fDRzZ{ zj;7#ay| z6&BvYo69P#D0`2GVRN^{#l$B%;K@3VEN45^GD^NHufp8)7Uf=wXFIK_%iQP_bBYW^ zug~j01Uzvw%%_;Gv;`ET|$c=BbAf&x`YY@to5Rz*n94Te^bnC>YKx+7cBQ?sP zD%V%q_j;N~R6d=$Z^-v^!_D@8&)re3%q9*$x!d?hRZ{x*qm!V%qw&w#0Am|Rb0>2b zW5u6Ee;d;uwr;2YGwuJsj$>>7M>_v9S+8rbGNwjF7VgM-@VDZRq9-OQ3KNfa5SMVn zZ4yMcGEHBlepCH`?RfDIgB>#Uji=9AwF#A5V4|OV_%YAB&bZFVyyorp0=@y5cC7hZ z7whu37pPw*hZE=8@mtM}+lM0IS?AtI*KGP)q8jJHL#r`eA&k39FgN*}3kez-0(nd< zD_o_Z@JvoE+Y$#jP2WI~0^ORvAiOXDi$uDXD!{W(wsrZiZ2uA`3ygP6A0j%cBLFj{ z>j2k)Vd90pVg(ih8`(@>f^h;lT~*MsFqpsnG)FI|4%I#Qydr>of^j7*QU4Gl@SM(i z!z3jNJ3!2(b6dUWoIgFMXwt|9q*E~W`BgueD#&E#{_6Mg+y|fhZyO#9AxETY>=`CZ(09c6z)r=(}%oMmk=8qaS;Z^ zFQ|7!auk%4?G}Aw`(!6mv_GC|M57aw;&IHv#o{Ow<;Nq|)ILHcw-YB<=<15}3cW&V ziYYZ%2NhgcmK-9~u#AXG`J2NETBUzL3)B|^0z%w`*kVGkKmYV^uqyecb`*V4-W7@+ zjVIcsXcRg|r`C7>9U(o;ni&Me`Vfx$}CQa4%Y62ci;afVu?|WKlXz>Vef^3 zqE>6LJ|$YXn|ZAlU`e`#^A+;HzwsO2j^8&wmt|~`fBlmD_usgr&CjK^fB5M?j8)M| z-^utNrh2KS>4rIo{571^8O{JM5-n{dL7)+`awi={a>JQA>Ob zS*KebvRYryc>Liw?*-G6@Ssw9d?wq1qUHcuW{aZN5` zEE>Ci&UOA7U5MF#?OVrs4zaHd8RlLe4#GN3jtvb+IkL(hh71-Pk^#S2Wr=J?y~K|% zR-sUnCg_sbLoIo?>~CgG&LZZVZpI8zg;K(m7hPK0kWXr;om7Z(J!?%G2%*H##tcyS zxK&q9T-B?g@syG#W!c0hJYAT|RT?0=D4`Vr3nu2MBL{4wgF>oy%Mtb%`qy37o?hoU zwNHbG>=u6kydqNf%}ZE0h{!;hRm@7LlP~o$NblVtWl$U|(M%}5=S+WcHGfTe$<9NG z5sMWd1gQbc%Cj4#&e0V&!t!b_058ktNtB7yTx{Up&}bjT(~wBt!exLiGc+G(k)RA- z-W!-2VvTIhCMUj(9&4S|Nhku5cdb^qS0xN~e+YQH{x@y+dV`2EKzC&q>9^%DHuoz8 zCkBLQ&`e}{N+33Xa)g;VnjRXfq|+Xu5nU;I|5WICH2@YN`JCTB526uYBK@Z& zyrOG^AVcK#qDx$|T_$#Gb^pE)bO}{4mI&%edkg9Z8N~Pq@0Dw*sVXegj~kM15ZcpT z<&TNTtP~bfQCBfM1e6)KQ0bJ=iFSf}3HGuQcLmv^%BOIdOiM;lXJ9lVd+$8ppPE?l z?%Km>Tr9x=Z^O5c;9f*GWJ#H+fIa6kgkHxN!$g|F`*`#1@qherL0~bKbGFs7nkPTG zLw2bN7gxEJ+nN}^vRh5%|4`GjP9kc<7JrE*rC@HK!AW`{7bQMP*;;_Z>CK10iDw&> zuh2639Ed>bCWekaM-LlT@23d2^z|4qH3jSLL4?RkV2daQve9@u65?ly;+Y>gTK^LE zZjPLcQE1V{Wlr z+RfMl>anL=ONZJm5c?XgGl@=*xKJ8B_q(TV^S-ArKwEAyY_|_su0~A$!>l^(?swJE zTeSuZDW`dEeX%D>@x04erRR^ygSN&ga^C&7Yv*AGGmu1dqeFdII*Sd9`CQf!^C;;)Ra;%StBKIw37X$J^git@d#Hm)Y%-_!h;>>i$Q zg+zeTvqR)$^7K)Ov+PPxGK5?~WoGk87I~A3Ei@X4DSeN#X?5gQZcB?JmmFk&+ybxe zV1L%0!!>TvmLe2a@MQAkGkP7baH)(daHscydlJ!H!zk(R6jTi^eybWh7^e`lhLa#% zd}Q;1$jXo3$in|pSwx-8*~Qo53_0qxqq;$0fld<9<&*w~Vv#jmr;I|kn)c}`ykQ(w zj;ddg_YWvAgSDi|Z0;e=2_-!}@<~E@X0m~s&QatFvAOMN@3Da8xAF5%8G_nPCuaW> z_joSm1MlfQ5K<~T;|RFgK@*TA?m(xWJ$MNauf`k#7=RVz=LqRnVZs}Rt`wo()<4}E zTv$B9%5@%%41ZQ2Sz}unmBmGNqRE*Ksm=Zzaet2l>@Dnnt-a-CPg|MYe@FA~ihy~{ z|CqtvQo>k${EWV_tFG+XVV*#Z6hc^K$7V-y?ytl`_q6AiDy)&yY>qO#YK07*jmj4D z)HQSj)%Ee>`+Zvax(3`3TQIS6?%0wI_OW^M%)mCf#_*#5BAPV;C_c7BivBU-$?N@F zKhBG(nDOP6-KX>59UBiJTveW&CP$`2WTHz9$PLgnjFp~dt55uvg=7%-6zUFUDwKEE z`PQ^UaJoCRdk=Td_9gkH{oLf}O?>YOYc@dryXyKz#^9ayHcmE`natJ;))N`a8;vA4~ffRvJ<1Fx3(eFjbCg)7*jT z52}Qh#_S-3Zu|Pbh1+||%^F&E)E&Xwtqprw;2ko`M=~BdLe!Z7BsU^|zEjeB(jPv! zF)P64fL#D=bDw4edx?kI25Y(yofe3TXYZU3p9o8 zM&VAI6^~YnvwM|Fk^_^`grTw;?0y_?V~%KYN=oPDh6Ba+x+92XJRzLaIj3W=h*SkW z1HeT)t~DzcZa=g=c_O7)aRGX~I$)6$7_C_%RXEdB1&p6P+(~tvus~DOYw6ML{9IJ; zz?9R9mxC{<)65lk59N{YuA?=oTdOB)fKRm0y}V$_7AZG}rHjBoV)iN><^;y%Q4s4B zH%fY~Sv%xqFmlPeyi1(N`o*Gb7VNB$tk0HQeXxEV$B&qeD)c$xiYCPes!N2v`z4a` zrAmOLW=qWAPYo+2_rhkQL}6#`m7=@P!J2ksj=;hk_Vq2gsjRB7XUrk`M9x5M`BhnF z2{8?a)i_Z<^Xruu1nM#At@P0Z13Z2j5qIkx_-M@*Xt$(3gzu}I z=@1leGooZ(zBkGE;yC{&4YpVkQh%sAoDk4I)9$0MtpEiM+d0@f0zMbN0(50}c-&fY zMf4Dp@9f9U3@8U&VETDpYIXIr{91?3Npo>EEh1TSZ%v}yBVS9`!Y z0@1vm>@)~#{3HWpcdKC4<#1<%^+Iw!5eL<%v6~=RuE49QHaU;sNIEkWTZXUU16OHw zctG5Xkm(Rr0Gs}Re)yF9I$ik}1x%&D^Y`u#Oul|#@;~6;|A`M*eFx+Jjej>PTmO`n za6U~7I_yQ#aj@QZqCEK}vJYOaz<%GmzkbChMkC7QQabQEdr9 zxDIexFpn9O<8MF?w4a^W)Gff^)v!PM1;r7mWfPO?(Dp=VZ;{=KGDe5*C9dqmD)QcNZ(<1xmVP zS}@TdQ({)8*=5~p#4~*wukTD!xJr?`Cg`uKqTzrVJ2_=jFc2jLHQOwUk81kgNlzhC ze>IVq`R`w5&f{D$83~0%!!v`dYt&YDhLwwAH|F%>MAC@>?msfvx+>(TTtE-QNfsf+ zg{T}8@dP{#)CDS9I4mO%kh^Q;U!BJx$(2ulRw4)c<--sM&1m=R>Yx3QZ*vqt`-_b% zMs$!Un1&NrT0=U@AgrLSBlaL`MB3b2cY&F3vA|-G{n^NR>Z!7}N~V+~k`aY3+D5c$ z2JLk4+n0!5Af?FOb_6sYR?u%J6_!cVq?If#^CR35_jyxv1SaX!0dv(AvlmJ`EpkhJ z=%GN2lae39!e z%9A}L_68@D3LJ)KnH-H^%Q>ibOvx{G-bkcy{nTTmqkf93_tH=WPpMt}x6+V;8!$oN zf9a|216S&u{UFKz2T8*JekJ=4lKxem$yE9WLr-fSau7%m%5p-#3lA^XAPBIkRix9D z=t}WtZ6#L|2rsoAU4?yvc>`&EeiMf6*7J_Bd8+cSm1X=KIdU;^Jx(<>Iew3+-u^|k zCyWFkK+#7pWEY`7Uq^{ieSeobWAUMuvId&IeBQS-rYtzF*@(dk8y-x)Ww#Fhv|zKz zOcj6OY~#3Ghi+4eUbJgN7pQRBN!E67xe0Yk=rhqs!AiMy^%YCjF8_d6l*by(^T0^8 z!Bm4Ai?0D+Rm}+nSn4zjIb#=9rh-saW$kvs83w(4Mu3w=H?PjWi z#$0T#DV&o&QZGUO1;S#hOeGA8H$rYQXP`-8P{!vo?GcrwGxgbaK;i7U>h|(De~+hM zhVRDxD%AfJY@S|gU#)?WF*xvpJ5nDY9?D|%9z6I|sTSF9%SIg4=$kvP7?&}@R;Egq zocrXZxO}4AbA#oe%^a#d1O(Zd(@d~| z2R+lQo=YAi3>jz$i!6Xhz`nJ>p(x}~p3DKQ2; zSnCF~XGWWWg2WZGj&bW7oL`cA$zP$C-!G52Tt9h`Qc#6#6~u%e#2^$|N^#|t!WC<` zWCe`Q=fg8J>uEIkf{RCqtGEq>I7wUIs8j#azRj2z_*90)1h+ zfGj1q+euJAg_!%uwg>A-oZYMwjDT^ zz@Ow%+&)IzZwM9cQp2c&K-Cy$D}w}rO2deQCN7lgJpI;aE|Gt=F=6E|oUZ?w(D)B4 z6OsQZnEtnnRH!H|yUvG{k(@#VZ4TB@5actPBsd2MA_Qwq0TiXwr~o8Z>af#9Pgy^r zqj?T}$a`byQMT}dbl$QvO;Q8_JNsMXBksxce=4})lmWr)AK%6V-s2xpoLmh+2FI1$DOm#Xfi(46e z_kO3Vdxek*adKe=&|UvoT5RRgDdKI*se&{uillbIt0sSH=dD4|G6BZ(`N1}L&Ift* z5k}^jO?N!roJjlbnp4=->amSb;M5?#M%ycC88$u)`~dZkro>yaepdmHsmq*NnioNx zq@F?tjwSq(fNHC4kYWi8_nTL-?*qEIIdC!$+|BaC!@^EC2)!H6jzsGZuv;j}&MhS$<*+c-;R{%dqn68Ol46tT5iXh}qhs582RE|Rq~jBi z?0s#bR(H5*WH}k5Z*;N_b~TzVW0(D%%H_YX71{1_rjDN&i}vF{_dn=n{}W^X5yJno zo2_*I|DKJJp|#RPDM^gbQd0Wsl53@Tt06}?GyudOU~sctvzajH(!8oIhdW4mLrVk@ zM#A$4R+y`PlVIhm20uM>JoUBfKGV_U=y^0o_ZP|yQy5qtgaO6g34Q{0b6G?%U6XVt z&6AYo_d&Qwzms#m$?3REC(XrJxN&-Q(0S_Bf<}KcmglA`b-Togy+1jAeI4Obpbnyo zvMo)L;sseQK^W4tW`otZuT;utldVa!z1i|}d!SmBjASZ5!d)O0!p4N}U5^pn7@D;W}Q zwX^9m^91S-AF{*j?+AojNN%!j8)x2iFDllHrQ6O#C}JxY?nM;HT@TFZ0hKr$#_vN7 zt44@nxU=5jnPTbc#+$gaQtZOofHfOFSu}x-T{?o{2mS3t^Jnl^IDrT~5qY%F8GqJg zyfoTTE?}=%Tdp1vwy@j8FuT(}u%n**d$iNh9ei+?!5--lYmB|JOm%H$3uoV?Et)m; z22XR%^ov;z`HkQxU&z`4v@_C+DqN~h@r@<_9YipI)79Zni%a0em${R4(HEoCEr}vV zMu7pCj$t?bXvO3dwjetj?6CN+gIX>`%H?bx=$ z3M4tv8$2`IJ$booFkfRTeW;kiZKplh|6cE^eHQNa|3Ks8r&;trCi4I19#Nvw=6?|R z@5{%rUi+Z<82>?kTrg_k=sR>p0ivih5@0C{u?K7N^rxCm%d4uBZUEV?*S-kazh(vx zi`}DWrqzkRfTeMteu&5u>wWs_dUkiW7hsLQGd2VPh7zFs109!ZXZRpyhZeF*CNB7} z$Mvm=(+3&nx8T?}Z|@Jzivr%TN!oOt20 z)592+H`Eb6@19B&C$gpMw_E}s_9q?F02GwoO?Y>ZxES-UlD|c$(u`e*e(^ZQ{RS%V zFlw|d=u>QqP6Z5Nf7};XzeU*!u^S8NYicMaT0dKW3XC6czg3xArgYVO9L)&$0J9Wb zWZ;&G-g3owr_xW8Xcu~{f^+h%>qh7P6GJ^X+$MGTsl{~Md%XlidEL})l{z+^G?h@q z=45ot3;R&FCD}~DXYmmr+|c&hW(0#0xZ}enoptR|+g$P-;edns6hJ%J8eVA=uq~=K&`Zro?d<1#mN#+x-c1fUX}!HB@Ulkt?5Jye&O_Y#!`NOB_2~fT9QBAGlt{0A zU~;wnHfk5h*?@qnG2)Z8@A86gRYNdy@Ssh5pm1AQr=Hl%d`_GUEx_f~>=ePMn8@)| zt~ZG=e_Yobv@u$I0cPbdsa+m%lJDTBUEI*W*ehch{HnYHioE<$R#UoLm8GMGC;4aK zd1K~xLS@6DWyQMsUHZppV{#8CGemQ-1rLuJBc#5m58aPiU8 z$Gv`*9V;0(xIaZ@4K5Mp8s3n=X_Lv*ndfX~e;gj$yDyHuhBSYpI_0GZ27ka$gxt#3 zz)3_5fnn$eK2X6+$rVvC6Z$E;Ph5Qd%U14Z$y+@54^|j{u)_E6vy1-|udtoxgY%AO zbGB1V1H#CWBa_23H`9W{!b27a=MxBDli+8!TPG?XQ0|Ccvhn*K2!a&Ddini9Hc*kN z^4b=tQD2}xZ?yGU%RRS+X(s=S>Q`31KgENX`A~jW5gz5 zkiziELK)Pu#lny~gbPBkN2P#!k#waiR83NBg^bm-`8-h;s2u*G<*5zc+3n1=;ERky zP=}l)pbD)i=t+u8ry99EG@8p#0<8L_h=S)W`mOBS5P_~M?u43n*4^37A7sSw#jPr#5fMq zLMZ3PlMlYDbtq}_B68xtfh12h`iKL8&Gw`uTYcI(q#NyWs!@hMris?lWch&%woEoL zh`P1XQR``vG%_cnS|_7BJU9d9u!bKnIJKKXX`jPnnlKbrY1wkEMKt+3@yX9=1t0w9!1DBNbr@3lIY3#R(~s{yK9>T*t4Vf)^xq`S6LJM@9Q^A79O3Vlw>x9EDjbN^B91@+40 zN%IpDvONEzX$O{Y`k_bt4dL`2qH!NrQ;24^c=M$C->*|L`q78h;282g{}RY) zlXDx~;D7ykApiGvuKtPO|C9ig8lHLyi;3TvMkZaO2Y>>2BX|-A_~K$>LVRL)Z~$h3 zKo&?Ca%agC$wqn%h^8cbR2JTgrj<*1z_mOY1(i#01o%U$n<|wtkBgO>&1Y*amse}W z&duRmPp;Qo4DnC`cHgPj?^oQ%8;(=l$F5VIqY)uEz7RcDt+b%(BP=^~yMdB)j7T<= z%^a0UF6|xtYgVA+&4HCuGMrjl2sg>g!5kbFIkttoX4Or7@SId5&#RgG?StWOg1w9S zzI0_EkSaC}ESiU3a;-QTm`{!^64Zw*v4Ampk;q_yO&O>gNKn?`RcA^Y@O~AFOhsYv zXyj(p{10G6%~@#m$~O}3NY72gfF9|$Vh@_ z*d-yG7ZY-^Dbpv*Ie`p&%0-IfBsu7{ZqVP7j*CU_QnSZ?GDFIpv`u&PBft#IhFOg5LGtzSfoiEu; zk0=bcNZkpXklESFBv<3;_(*FTuz?P`Jp8gFT3cDf%6`^kKU=Ucg=|9g?s5$Yt-!dl zfl~Zhm^ZVeQOVol3kXwIlm3f#2Ir?aScD7>PdilT-c7@!lNjMRW45D(c&sliAb}Cq zW7bRn{j{X!Q=y2Z%Q7423?M288zVg;6J-K;Tuj;lf(Fa7LkU8|q@SxU$1c@x7&BCY zTRig8Dqx;B03Pe&=Xpzrra?FosCysF%j@+#ylJB5?tslpNt#|Wgu>}#{q~5 ztlYm)Rg}mRL6{Hf1Ell|e*YpLXy#j%uLXWjCo!>dyXM9peQY5@DljoV3WidGAD$V7 zc{XU$KSNB_kqG7$SlD?`aI?t8qCCt-Ya#;%cz$Cet9KF|i&u-%U{CQWMZ&6|7=(t| z9=(f1?L!zCLS#r<{im290B9vkql)qu3gY&h zcfS&)00Z`*&X|}I`aCj{$;7QQ2F37t^GZ;z~j;5@wH%*kH_h5O99KbNnyT&)#yr*%|@O)9Fn#3s*X@xEY#23p+Ew`e-ksv-+2Xt>#DdtMwKHSm6FX1tF z7x0PC2oZf%VH~aN+E3A8zd*k&cYeOHw-|h$S+=tMiqcaBP>FBv9()+G4Y7$oKGynl~al8b1|FBdDXMn2>hBP>Aaw;VX3h$v51{J@k zdgd8qb5FBY6sU+Hie)3DXdgr&Du2nkcU=i&Z;nCTPZE8NF&*A2 z0^f%mo;1KE36K*oiQmF|3^Q9~q8BBUiHsr2X9^ls@~&MarC#V*R_f6qQ5!`g2P-Tz zme|nI&mrW`Rs?B|Xs~r!y-6i2-itT1tFaTas z)9-$ZhULh+^eI!O-v~gE+}&~HuxGin^Rk+pnnBTE#Tk_)@c_x)m@`@shT45~{Hn#E zBeDoXdkejiWEz$1a(ge2Cg;z#Q7nvZ$B|G%YJ^6wfak@>6LG?D7qpkIqbAn3Dq>`$ zlsVR0#&*VKWM9u897w+a)-7N(UMUVyb2TNHV8DK79B2>UhDTbe3wwn#)pnie7=|~G z2ca3lXiwYMM=b?^i*xo~s*y!sD?ST8?Fd~I0i2MN;OyOm3JQA*GmD54nXA55dhUsx zqQh4-Ps$m^^qL+3(-$``oKa=&7vE>o`>Tw)cp$9f!M&)NR_kmm)l4Fx!*S0?tYq4x zq-pNQ*wgr$5odD=FQ9*h=NZGNk|_QtWtJA(Zc;-r?APiT9esel#6px(vKp`DeiLi28mAEk3mUVyNS|Cxa0qq+ArUr$OO=~ z(Y7gMEXxTALa@nkIk?qgP1kO20>`(2T(FDrWB)9iu!4c+J`mp(>bt6Q3pZ?rkY4}7 za!(S;2#fWg-G6PrH2@naByd=&KX}8jBjhcOT4hD%S>Xs=u#5M@^FY}=aZBoRfShYU z7G&qZ5lBS92&TKvh^AY#KYwd6`}<`=)z=2-Zm8Un+b3S-b2kFZ^v3dM`4&VZ@qw`W z6h88DFiyB$Yj(1#(ZS%&3zb-6Cc$(moJ^?;sg=nI@M=XzqI*Ox) zBbS1OIj9ky@|xQ*htkA_a}o6zCJ*|+)7~)E`LMbO7k`r%*EM<>)pSp(?m0Z|dSPDe zeIh*SUGb`Mzeon#O7&wlPMwcHJ!e`05yeiOnoC2+wn5*eirTa%hXUiO1|5Ws>1NRu*i9 zZTMIni)?-|sf#I{Dwud`d%wt_xaeiX9fntzH1^Z(*HJ=Cn-7rF(w+}vBRQFVxq8|) z6LhtMZmUjHC)!lEgYvHUc~x`j(+%5z#e6cWI zXwu>ENclx!H0)V5>}oai`{Sn9z;AwZLjB$dg|QNaYlrVMJQ*fc##t-++ zfefit7txEz_*3bC&{hbCDoNi&4?!C%qD66TpK3L5I2T5FfS^Ubyid^zt2z$&u@!NC z0KS1Yy({95%sL*@BK#G6c}H)PJdG9_VkfGC;&S@p`$udBI(cDC;b_oBD$ckr!?r!O z%VHwO#KbD8ZQw+$oL+q@p?)V84CS_^HN$;A)P(!|sEz%$*`Nc@G=3@vhF*u2`dv)L zZXyW7T}$O|vXp@$*3YXv$-`vR?KPiigyQHJ$z4}vJUJ!cn5aisk(q&a`fvo`0J{$g z&=J~-&Ti`W1bt1H-O~diOirjRsQj=l;5v+4{%6Tn4Apfp8?hy?mKXNO0~<%y@H2BA z3yhj$OP2s-{y=T=FScI<^b_srW83lm?ji{H4h#`=!J#YC@Xy8w__{xK9Pq2}C)9h< z9ZNCZ5G1&yGhE`oJlewCZs&DADsrj9guLB&AT8f-ApqYNB}CP6bqJy8*A3|clNZy2 zbC)T#>FI4L=)VQ%F&I-YyCuNf(*=C`vFHpG96H$T$t@Q&u_m}EHgTLbqDFOGi>xmC zIgy$`<3WlvgJp2Lrq8FoFL^$)%H@K-l?<{8-N;rs^$&bUeuuCQpP%+;*CBfgKWP>F zFLaZqC%Vu8i)*yUFKTLW=J%8`y!Lv(xK%k$@46z7f8|oe5{>g82Jv7mU3lDv6&eza z-x86q8as+$`48dHo5?GiZ{*O&Ng6_Aa5ET09t>VM6wx!W?+F-Igj7>r#(spvqdCya z99_$*#o+p*!sesJ=%L^YS`Y*VbqYcH!{Yw z|Ip%ci(a|yIG}$w*+-4MK`lg~701*`qIMIu87jX6&`D0d0lD3k#`a{bb=wXuoGYkH zqx_Ovf;WV!axc%IMWwUl?NM6oS;eYyj`I?puN>N+ID|}HuMa~oJ(IExAWmY6PrgkX zv2c%i-N>8YbH5Fn9C?9#7{Wv#+%9Hc4G~fI>$Egi2zo8*ap{CROjX+4uEh7Ug%6K}MjOaE1hJt5{zf zB!?!!hGf=bjZofP;iVc?`fIv>Z<-I}vx>VH7Zxb}+Ftbh)|^=|dw2Zcpr(&!Y=E zsZ%n6aD>F-{&l@Ts_bfy*Vn`6(q-T0iFa=bQI->L!F51V3B>Y!xvI_yBt3`R+S~Pw zwx+W>JJV;;QLY9|#lNEm9keeqGO%+Q zg&G^$<35l6pVH0)oXWS4<3^%vjvcc1CL}9+9DA10A$uH~V~^~SRme&Xk`c-bWk-Y* zGLkfi>=l*w@%PrL=U=M#eXh&p829gU@B4o4@%{1E8*OC1zCDnUTF@j;RW9d3v#Osb z!R5hB9*FTy7Bb6kRSNBPe{{;=i%~R3(UEGV9`AfQ%BQmiMG%T2lUwAhYgVh(c)j&u z_g?q*rrDT07pu8)JCRF>|B*mx@5Fsh1ZPH>P4M7HV@aKs*}#<554mYDb9E;skOyOU`I(8sqwMaX@&lTdShwUy}~ zn9?71Gda^#+zt0WyyM8nQ@OP(2#H)rODneAd)onQx!x-ZxFd#*(E_z+e7APaWB0EE)fkA4H7G)$aDcm4wWhJByy$v zR;t98jtkRPJ3gW%#o5~Ex3wjo)l(%K;Y4cEya`vyhlEAA;GWBKupJsqaKeyNV9PzF z+W9Fo!%X<9xwdLkWo*wf9qc=4FbW z;jq&bqiuMUP!NBKloC;g;mc-8sVEk~5I5^1odbz_(^q}k;}kO=*I-N$i?7m=F={hg zN~a6?O3?;q!UXWUJp9pS@RgJaTXk*`g%|Cf3axNuLo2q(3<0$?vx$rFGciQK`?0g}oa!ON)7Yqov~Vx|3ex z@}leRIciocud*pAv&!S*L(vSeE9;O93tq9$5}Ynx;F&aNM9wg6vp4xJAJ00r-ayvFK@eaP84??3)ogn&f~C7g zC>XoS$t~H%v4_@S0a)LKY@b`HB}35SRvbAu3b*;};(avS&un$YiWZAI*`K-LLEgzC zS*S6@r!j$NJy-O&eqnawX*g$BpO3xUqe~T~1(>{ZaP^XOfrd zTvuHb+Vp83kz{XnKJU05Z=%t7g6?!M@$;yKZrRIY1)w<$^ezrc+9ycO=la2b>7amWw zCpmMgPCRE1Z6qXMPjph+gHHw{R0v#GiRZ_!R zpmZnL&}UyqNz^Y&LEziS5}Kr}(0NhO=g{`m@0Gk?~~5fy#;7c~f1|j8hCd+Tn6!bMD*aXB#qhrrNfsg5rvTg6Rd9MAi$2 zJ?TGZ<4DVx$QcmL@2);cMPN@#O~7@c)0pWOk1aktI;&1F(HU+WEi%1rgd=Ld-I;p! z>P_e^<$H~o)!V1L6GUw_Uh=qg%YEdLV)EY{8uh1r=66f4U!6r|MQwyQe!|H3v-h?l zek1RdFWelvjMM2%S9lX2@^OqDE1YNxM#>qle>q3=d7C(JLPn{6jg+2mFipBiQa>FNjZq4pyi-9ybJU1V~4ey0!Y(HMJ7sgA|e+bxL%oK zS>@M6gtVBIV~tbZh}4y!)6OQ-$rF*AP~sa8g$G9D?rs;5ZT@$z~{o?_X2Cs(- zi@WeP8zV9l>Y&=`sjhog;ZFEl zd%-F3h|){#8FO{k@?NT)c+NVf_|ha!_|~3llOLUYKC8zrYQucBcPF53% zv}dl!Fd|+M%Ms$&t#4w%ePX6(@RH+ci|$fH!FEpg$QDdKeauqw?(0e9qW2f>^O?rzbk>+)kni+vg0vcar&hyF2(zEi%s4&|i#@|zEen$U{vAof7 zEFg+ooJ>m3msDG}<$jQkavCP9=HL-Y>RJ)pOOmaLhP}FH<)^DoW{Ar_i4@I-W)!d% z(Kgr7%&$c25?rRGS*Kc|%=N3Wa2BS%Ctp`-bJk zIldoTkq`26Ukq@tRRmDqQvPi#a)aAjS$h15WOYIEBMl4zz-ixc48|AB&L(j*n5_IX z-ex2nb&RT^uI3RlT7p8^siD(l9#*efv6u7Wc&-bGX_MX)EBd?}R8#~tpUN>uJ7K|g znF?8@Ou-+ECkN%6dLyuP`gMfAOp@PipA#u=O)_;hWjO{DL-;K5NURNeK|I9M^4KVQ zL2Ak*h}>Hv`Lnr#NYyvvC*1H#ljL&ph`64!Xd0>~xU=(TiK1 zHj+^m7^Tq>I@gl`zO#oKn0)alHumTP+ACfSMcVn$IxsLrRO{5gc!Rlk^vvpHp#kG+ zyytG_MyN0adNq|7>1OAW=&f{kPxI=m&M5AQPsO#jKA`y-@k@6k2&aGMV&%=a;vgu5 z*nD|xVNl(=!qLK-*%{W+-Z~o0XrQ!BJ3-{WNyeP>)y`2Xi@ua%U zyQ0C*M^ZB!j7Bykek^YX=O*Ccp?d4qi>fA@w1(r_(Emem~Rhji^Zt7Tp} zYZoFw6uB-~oib*^>WapiXCQH1kk#t_B$U3mh&kazE&G&xR-)G^_GsiamoY&oOQ_2B z^1{~EuH>H6$F1Dl`)K~{+GJP|F7{^?A%b$|oKw>RTZOML`D-M(m+Y5&ql_5Ej6B!k z+-+5A6)+ejRX@eIVO$KO+iOiyBiz}orNLc)NRpf zV`ed4jSJVtRy&7vtN4@*y)u0R`xgmXg~ufchr|i3pU&x5^tr5*8ha0Ju#^-uXA#Ls zrrhss1%$}_Pf!+!r_vEBnnZJ(N3%$hMI#EPOEjgdY`539ljl53!{aD7$FirrrQT^g zV48BRCP{*;66U57D7zC6T$&cM;af>H@+@s|D?GEqEx4DxS2_F$?|L}Tnn;y4#v`f7 zXwMXJYisKl+b)D&Hsn|f=|*NzO9T9sHQX|!_i+6Qce(2Bg~s;vTozg1roX#Q5s(?y zY^-#?epZ&Cp+2FxUpAv&(ZF*XbP=SNq}UP?69X(a8)t}Id zdzf6KVyP*zcPzH-adp4+kSsj?h!L7_LC_SIvTACnShhw$VtB{+WG&oVMS*_A3Z3t! zaM~+-5Av)8GzCr}-qn)9nNP!ep6ddeH_ZK~?#*x{xkwlfrh}SoJb9#h>dpaMyzCZA6qW`LO1TZ zVEK7A)k&8-jA$bR${ToUF>O_GzahyNOQg$ll9T#R5vEE#aVXB=o zm$I`Tbwm7n5}g1VWAAnBD_$5`4@M05#0WK}Y0(?Cy+wTYGTnKeAH5{3(j8bT0tWb z?rWg;o=ApTU^>3@n0hj?KQ&v*>mxa=Yg0Ct-F>K~&%_n2bwe@kU~iwvG}C;W@;p_e zmOm$Oty#Trge@3J$kO6j!0pZWu*@qRzp$X+xvQl{&M~^?V?pxXidnwG8XtN=@&9v|o_T0Vb193Dy5Qx8i zb8d}i?9|PAm%6o~p*zdBckf*~q4w52FP;`_^~on4iJ5G5+M=MOUTCn?QRDeiksSic z0R&`dK)#^2Vm3m|%Uiq7=1xAD{!?d|g{YNw`9)J`Rr;$ z7ewIkgcH20)y{W8vz2U!)bb}bIr2_>l%6N0qUco zFrMcvAFJ@d_^>!SitvlikJS;7DTwlylIt}umU$Vb_YBI=SV-(`9%~UM^0rL#mX^&- z_o^h9g%Cvh@Z33WN2$=G?Y-j&%^Y?aNG0Ra9V2odhze-&x-Rz-8(&O1amv)*_bALU z3%=WAMMn2zhpK<6`elR^m$MnPPs%uQT>{z98JN1Ur&yXgCnUNGRi*9JoU__2jGzy_ zBXm!HPrI|_IezeYC6*88k@S&^b@9D->L%69VIk_I(#BHbFCNEe3KD2M-Drn9SYvb~HrTK+ zi@$erC7H}1OLANQaJHSne#+8)C?z2A$@-#nog{fwu}6pbGU*jJ=#r+uAg?uJUjn$HtVay=Od5hcn+iPGR}4L#(qV=tvo$d)c2w z$p2s6jEfr_=zl!ytlZVOIlI->)OlCbEBm0_YJEdIe5%~+$~>=B`Fi+x&|=}230fOQD6Rbr*)2a~o2UTF;1b+MNL58papTG5|P+1KXMFm|wUZ~<>V4y4h z@3Rly13m*?Ffc9qbyNXW)bBzt0I}E)anNZW8W1>&_FcgJ=zkaRp!+|JOZ7E0+I~zC zKMVeKcsR@q?GI)u4l}baa(kF5!XHe{1E#*^{_m5+{zG6&;N1}v_?JWBVNu!_?LBz* zGs)~Pto{?@Zv*TB16AoVl{(N}0mHaJA^|a?Zx1r0>U)N~f|i1Yyn=?Dih?fK#NE5E zBAkFMGvh`BN)YuRLkxiF-?zl8tH>#6=qi9i*WdT94F&?00$-?nM?*t~tdM*cT0>J0 z2oDZiJ6y;vNttZ%W@l~p)x{V%;zou7MPxwjDZW$9HIJ%O44JI8;CmOMNrFp9?j> z;Q7mHp#}4>m34Qwa?s7WYzbIKbA#JvY82xXt0`KJ3b~c`XnxY;27v&3fj{cQ_3=whq zJ>W-I>EQAN`xZpm*6}^W_WqFndryO47}(bu3U)i-4`F|@j0MJm{S%?EtD(Qaez$n? z3vWeW7}&oK3YL56&tagI8ZZRxCI$tOjQDfN_si*E0@%X=itsx2&j|-tB$x$$-WtIU z1W=5*xW8t|{?eTQIB8%ta};(c@qfb}WaNLf&A~XZJTwZolJeKML&T!NT(IyfihDWz zuepCD0}GA;Se6qN1NY3oj=^CfonSCnwhIOB&HrogAtGL2E?5T%#a%1>Ywkg%lKrVF z5*Q4YjX{AWZ~c#8u!sy82^QBtA!Ew^N8~|o@tsH-m!u>99!B>k>;MwZG2LCo!!8c4%G)>@T{JtqThrw6xQ0U5ge~bS4 z7y~{Mh9da&{f6+b?dP8pz+2iV0`0TEB^)*)gE#$99Lv$)asGS@5L`mwttS*!ckDM* z@XY+Xxzul_H{i_=6jX8IyG4wH#Ur4C{>4@ZIDOy+P!y`{<^O|1Er)8UVF7P7`_2|c O(fWavBF*XjpZ){(@cW1W diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index ab8de201..7c6b218b 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,2 +1,3 @@ +wrapperVersion=3.3.4 +distributionType=only-script distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar diff --git a/e2e/build.gradle.kts b/e2e/build.gradle.kts index 144a3d32..e90bf2c2 100644 --- a/e2e/build.gradle.kts +++ b/e2e/build.gradle.kts @@ -52,8 +52,7 @@ val buildChallenges = tasks.register("buildChallenges") { val isWindows = System.getProperty("os.name").lowercase().contains("win") val executable = if (isWindows) listOf("cmd", "/c", "mvnw.cmd") else listOf("./mvnw") - // Use 'clean' to avoid multiple jars causing singleFile to fail - commandLine(executable + listOf("-q", "clean", "package", "-DskipTests")) + commandLine(executable + listOf("-q", "package", "-DskipTests")) // Pass the correct JAVA_HOME to Maven if we needed a custom toolchain if (javaLauncherProvider != null) { @@ -74,7 +73,8 @@ val buildChallenges = tasks.register("buildChallenges") { val builtJar = fileTree("../target") { include("Challenges-*.jar") exclude("*sources*", "*javadoc*") - }.singleFile + }.files.maxByOrNull { it.lastModified() } + ?: throw GradleException("No Challenges jar found in target/") builtJar.copyTo(outputJar.get().asFile, overwrite = true) } diff --git a/mvnw b/mvnw index 5e9618ca..bd8896bf 100755 --- a/mvnw +++ b/mvnw @@ -19,314 +19,277 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.3.2 -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir +# Apache Maven Wrapper startup batch script, version 3.3.4 # # Optional ENV vars # ----------------- -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output # ---------------------------------------------------------------------------- -if [ -z "$MAVEN_SKIP_RC" ]; then - - if [ -f /usr/local/etc/mavenrc ]; then - . /usr/local/etc/mavenrc - fi - - if [ -f /etc/mavenrc ]; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ]; then - . "$HOME/.mavenrc" - fi - -fi +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x -# OS specific support. $var _must_ be set to either true or false. -cygwin=false -darwin=false -mingw=false +# OS specific support. +native_path() { printf %s\\n "$1"; } case "$(uname)" in -CYGWIN*) cygwin=true ;; -MINGW*) mingw=true ;; -Darwin*) - darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - JAVA_HOME="$(/usr/libexec/java_home)" - export JAVA_HOME - else - JAVA_HOME="/Library/Java/Home" - export JAVA_HOME - fi - fi +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } ;; esac -if [ -z "$JAVA_HOME" ]; then - if [ -r /etc/gentoo-release ]; then - JAVA_HOME=$(java-config --jre-home) - fi -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin; then - [ -n "$JAVA_HOME" ] \ - && JAVA_HOME=$(cygpath --unix "$JAVA_HOME") - [ -n "$CLASSPATH" ] \ - && CLASSPATH=$(cygpath --path --unix "$CLASSPATH") -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw; then - [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] \ - && JAVA_HOME="$( - cd "$JAVA_HOME" || ( - echo "cannot cd into $JAVA_HOME." >&2 - exit 1 - ) - pwd - )" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="$(which javac)" - if [ -n "$javaExecutable" ] && ! [ "$(expr "$javaExecutable" : '\([^ ]*\)')" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=$(which readlink) - if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then - if $darwin; then - javaHome="$(dirname "$javaExecutable")" - javaExecutable="$(cd "$javaHome" && pwd -P)/javac" - else - javaExecutable="$(readlink -f "$javaExecutable")" - fi - javaHome="$(dirname "$javaExecutable")" - javaHome=$(expr "$javaHome" : '\(.*\)/bin') - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ]; then - if [ -n "$JAVA_HOME" ]; then +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then if [ -x "$JAVA_HOME/jre/sh/java" ]; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" else JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi fi else JAVACMD="$( - \unset -f command 2>/dev/null - \command -v java - )" - fi -fi + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : -if [ ! -x "$JAVACMD" ]; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ]; then - echo "Warning: JAVA_HOME environment variable is not set." >&2 -fi - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - if [ -z "$1" ]; then - echo "Path not specified to find_maven_basedir" >&2 - return 1 + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi fi +} - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ]; do - if [ -d "$wdir"/.mvn ]; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=$( - cd "$wdir/.." || exit 1 - pwd - ) - fi - # end of workaround +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" done - printf '%s' "$( - cd "$basedir" || exit 1 - pwd - )" + printf %x\\n $h } -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - # Remove \r in case we run on Windows within Git Bash - # and check out the repository with auto CRLF management - # enabled. Otherwise, we may read lines that are delimited with - # \r\n and produce $'-Xarg\r' rather than -Xarg due to word - # splitting rules. - tr -s '\r\n' ' ' <"$1" - fi +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 } -log() { - if [ "$MVNW_VERBOSE" = true ]; then - printf '%s\n' "$1" - fi +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' } -BASE_DIR=$(find_maven_basedir "$(dirname "$0")") -if [ -z "$BASE_DIR" ]; then - exit 1 +scriptDir="$(dirname "$0")" +scriptName="$(basename "$0")" + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" fi -MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -export MAVEN_PROJECTBASEDIR -log "$MAVEN_PROJECTBASEDIR" - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" -if [ -r "$wrapperJarPath" ]; then - log "Found $wrapperJarPath" +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT else - log "Couldn't find $wrapperJarPath, downloading it ..." + die "cannot create temp dir" +fi - if [ -n "$MVNW_REPOURL" ]; then - wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" - else - wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" - fi - while IFS="=" read -r key value; do - # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) - safeValue=$(echo "$value" | tr -d '\r') - case "$key" in wrapperUrl) - wrapperUrl="$safeValue" - break - ;; - esac - done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" - log "Downloading from: $wrapperUrl" - - if $cygwin; then - wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") - fi +mkdir -p -- "${MAVEN_HOME%/*}" - if command -v wget >/dev/null; then - log "Found wget ... using wget" - [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - else - wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - fi - elif command -v curl >/dev/null; then - log "Found curl ... using curl" - [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" - else - curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" - fi - else - log "Falling back to using Java to download" - javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" - javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaSource=$(cygpath --path --windows "$javaSource") - javaClass=$(cygpath --path --windows "$javaClass") - fi - if [ -e "$javaSource" ]; then - if [ ! -e "$javaClass" ]; then - log " - Compiling MavenWrapperDownloader.java ..." - ("$JAVA_HOME/bin/javac" "$javaSource") - fi - if [ -e "$javaClass" ]; then - log " - Running MavenWrapperDownloader.java ..." - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" - fi - fi - fi +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" fi -########################################################################################## -# End of extension -########################################################################################## -# If specified, validate the SHA-256 sum of the Maven wrapper jar file -wrapperSha256Sum="" -while IFS="=" read -r key value; do - case "$key" in wrapperSha256Sum) - wrapperSha256Sum=$value - break - ;; - esac -done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" -if [ -n "$wrapperSha256Sum" ]; then - wrapperSha256Result=false - if command -v sha256sum >/dev/null; then - if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c >/dev/null 2>&1; then - wrapperSha256Result=true +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then + distributionSha256Result=true fi elif command -v shasum >/dev/null; then - if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c >/dev/null 2>&1; then - wrapperSha256Result=true + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true fi else echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 - echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 exit 1 fi - if [ $wrapperSha256Result = false ]; then - echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 - echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 - echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 exit 1 fi fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +actualDistributionDir="" -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$JAVA_HOME" ] \ - && JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") - [ -n "$CLASSPATH" ] \ - && CLASSPATH=$(cygpath --path --windows "$CLASSPATH") - [ -n "$MAVEN_PROJECTBASEDIR" ] \ - && MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") +# First try the expected directory name (for regular distributions) +if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then + if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then + actualDistributionDir="$distributionUrlNameMain" + fi fi -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" -export MAVEN_CMD_LINE_ARGS +# If not found, search for any directory with the Maven executable (for snapshots) +if [ -z "$actualDistributionDir" ]; then + # enable globbing to iterate over items + set +f + for dir in "$TMP_DOWNLOAD_DIR"/*; do + if [ -d "$dir" ]; then + if [ -f "$dir/bin/$MVN_CMD" ]; then + actualDistributionDir="$(basename "$dir")" + break + fi + fi + done + set -f +fi + +if [ -z "$actualDistributionDir" ]; then + verbose "Contents of $TMP_DOWNLOAD_DIR:" + verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" + die "Could not find Maven distribution directory in extracted archive" +fi -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain +verbose "Found extracted Maven distribution directory: $actualDistributionDir" +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" -# shellcheck disable=SC2086 # safe args -exec "$JAVACMD" \ - $MAVEN_OPTS \ - $MAVEN_DEBUG_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" +clean || : +exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd index 4136715f..92450f93 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -1,3 +1,4 @@ +<# : batch portion @REM ---------------------------------------------------------------------------- @REM Licensed to the Apache Software Foundation (ASF) under one @REM or more contributor license agreements. See the NOTICE file @@ -18,189 +19,171 @@ @REM ---------------------------------------------------------------------------- @REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.3.2 -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir +@REM Apache Maven Wrapper startup batch script, version 3.3.4 @REM @REM Optional ENV vars -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output @REM ---------------------------------------------------------------------------- -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. >&2 -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. >&2 -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. >&2 -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. >&2 -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %WRAPPER_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file -SET WRAPPER_SHA_256_SUM="" -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) ) -IF NOT %WRAPPER_SHA_256_SUM%=="" ( - powershell -Command "&{"^ - "Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash;"^ - "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ - "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ - " Write-Error 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ - " Write-Error 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ - " Write-Error 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ - " exit 1;"^ - "}"^ - "}" - if ERRORLEVEL 1 goto error -) - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' + +$MAVEN_M2_PATH = "$HOME/.m2" +if ($env:MAVEN_USER_HOME) { + $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" +} + +if (-not (Test-Path -Path $MAVEN_M2_PATH)) { + New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null +} + +$MAVEN_WRAPPER_DISTS = $null +if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { + $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" +} else { + $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" +} + +$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" +$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +$actualDistributionDir = "" + +# First try the expected directory name (for regular distributions) +$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" +$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" +if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { + $actualDistributionDir = $distributionUrlNameMain +} + +# If not found, search for any directory with the Maven executable (for snapshots) +if (!$actualDistributionDir) { + Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { + $testPath = Join-Path $_.FullName "bin/$MVN_CMD" + if (Test-Path -Path $testPath -PathType Leaf) { + $actualDistributionDir = $_.Name + } + } +} + +if (!$actualDistributionDir) { + Write-Error "Could not find Maven distribution directory in extracted archive" +} + +Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" From 64a98f4f4f086f1c3a48da49c2680abd5fbb7ae1 Mon Sep 17 00:00:00 2001 From: tastybento Date: Wed, 12 Aug 2026 22:59:23 -0700 Subject: [PATCH 12/15] build: pin and verify the Maven distribution, tighten wrapper inputs Finishes the scripts-only wrapper migration: - Bump the wrapper distribution 3.9.6 (Jan 2024) -> 3.9.12 and set distributionSha256Sum. With the wrapper jar gone, mvnw fetches a 9 MB Maven distribution at build time, so without a checksum there was no committed artifact *and* no verification. 3.9.12 also ships newer jansi/guava, which silences the sun.misc.Unsafe restricted-method warnings 3.9.6 emits on every build under JDK 25. - Add ../.mvn and ../mvnw as buildChallenges inputs. The wrapper pins the Maven version, so bumping it has to retrigger the build - without this the commit above would not have rebuilt anything. - Use [${java.version},) in the enforcer rule so it tracks the property at the top of the pom instead of going stale. Verified that POM interpolation resolves this to the pom property, not the JVM's java.version system property. - Drop a stray blank line left by removing the Maven step from e2e.yml. Verified on macOS/arm64: mvn test 522/522 on both JDK 21 and 25, and the full plugwrightTest suite 4/4 green from a clean target/. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01SBMBsT7vUtgBXUk3gtajgt --- .github/workflows/e2e.yml | 1 - .mvn/wrapper/maven-wrapper.properties | 3 ++- e2e/build.gradle.kts | 3 +++ pom.xml | 4 ++-- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 2428c51a..feba4bc6 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -61,7 +61,6 @@ jobs: # (mineflayer/minecraft-data must support the target Minecraft version). key: e2e-npm-${{ hashFiles('e2e/src/test/e2e/package-lock.json') }} - - name: Run E2E tests working-directory: e2e env: diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 7c6b218b..533e7754 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,3 +1,4 @@ wrapperVersion=3.3.4 distributionType=only-script -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip +distributionSha256Sum=305773a68d6ddfd413df58c82b3f8050e89778e777f3a745c8e5b8cbea4018ef diff --git a/e2e/build.gradle.kts b/e2e/build.gradle.kts index e90bf2c2..eb0cdcbc 100644 --- a/e2e/build.gradle.kts +++ b/e2e/build.gradle.kts @@ -49,6 +49,9 @@ val buildChallenges = tasks.register("buildChallenges") { inputs.dir(file("../src")) inputs.file(file("../pom.xml")) + // The wrapper pins the Maven version, so a bump there has to retrigger the build too. + inputs.dir(file("../.mvn")) + inputs.file(file("../mvnw")) val isWindows = System.getProperty("os.name").lowercase().contains("win") val executable = if (isWindows) listOf("cmd", "/c", "mvnw.cmd") else listOf("./mvnw") diff --git a/pom.xml b/pom.xml index f2f97282..ac3bd614 100644 --- a/pom.xml +++ b/pom.xml @@ -283,8 +283,8 @@ - [21,) - Incorrect Java version! This project requires Java 21 or higher. + [${java.version},) + Incorrect Java version! This project requires Java ${java.version} or higher. From 0e8ac999445a81ca668bec6c27c688eb4e7cb9eb Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 5 Sep 2026 11:45:05 -0700 Subject: [PATCH 13/15] Update pom.xml - v1.8.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ac3bd614..eeeae221 100644 --- a/pom.xml +++ b/pom.xml @@ -53,7 +53,7 @@ ${build.version}-SNAPSHOT - 1.8.0 + 1.8.1 -LOCAL BentoBoxWorld_Challenges From d75d69f610d3ad4d7279988feb65ceb42e962995 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 5 Sep 2026 11:45:45 -0700 Subject: [PATCH 14/15] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index b8cd9ad3..8ec4bdfa 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,6 @@ Add-on for BentoBox to provide challenges for any BentoBox GameMode. Challenges can be to collect items, to have items or blocks nearby, to amass an amount of money or island levels, or to have accomplished some player statistic. Each challenge can reward the player with money, experience points, blocks, items, or other things, like permissions, Pre-built challenges are available and there is also a Web Library of pre-built ones. Customize them to fit your needs! -![Challenges](https://github.com/BentoBoxWorld/Challenges/assets/4407265/9b3c5278-3a9d-45f2-9ee1-2c1fc1199a8d) - ## How to use 1. Place the addon jar in the addons folder of the BentoBox plugin From 1d7bfdaeffc13a52850496aac673118d63d79fd3 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 5 Sep 2026 11:47:34 -0700 Subject: [PATCH 15/15] fix: ignore anvil repair cost when matching required inventory items Items that pass through an anvil (e.g. enchanted books combined for a higher level) gain a repair_cost component. The strict ItemStack#isSimilar check in TryToComplete treated such items as different from the admin-configured requirement, so the challenge could not be completed without enabling "ignore metadata", which then accepts any enchanted book. Add Utils.withoutRepairCost / isSimilarIgnoringRepairCost, which clear the repair cost on a copy of both items before the normal strict comparison, and use them for inventory matching and for the GUI item grouping. Enchantments, names, lore and all other meta are still compared. Fixes #433 Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01SYkfNqJY8BjLmWTDp32R4Q --- .../challenges/tasks/TryToComplete.java | 8 +- .../bentobox/challenges/utils/Utils.java | 52 ++++++++ .../challenges/tasks/TryToCompleteTest.java | 122 ++++++++++++++++++ 3 files changed, 179 insertions(+), 3 deletions(-) diff --git a/src/main/java/world/bentobox/challenges/tasks/TryToComplete.java b/src/main/java/world/bentobox/challenges/tasks/TryToComplete.java index 15fa3da2..40333969 100644 --- a/src/main/java/world/bentobox/challenges/tasks/TryToComplete.java +++ b/src/main/java/world/bentobox/challenges/tasks/TryToComplete.java @@ -1993,7 +1993,8 @@ private boolean hasRequiredTeamPresence() * Checks if two items match, considering the ignore-metadata setting. For potion-like materials * that are in the ignore-metadata set, compares the base potion type while ignoring other metadata. * For non-potion materials in the ignore-metadata set, uses type-only comparison. For materials - * not in the ignore-metadata set, uses full similarity comparison. + * not in the ignore-metadata set, uses full similarity comparison, except that the anvil + * repair cost component is ignored. * * @param candidate candidate item from inventory * @param required required item template @@ -2012,10 +2013,11 @@ private static boolean itemsMatch(ItemStack candidate, ItemStack required, Set 0) { + ((Repairable) meta).setRepairCost(repairCost); + } + book.setItemMeta(meta); + return book; + } + + @Test + void testInventoryChallengeEnchantedBookFromAnvilMatches() { + // Required: Unbreaking III book with no repair cost (as configured by an admin) + InventoryRequirements req = new InventoryRequirements(); + ItemStack requiredBook = createEnchantedBook(Enchantment.UNBREAKING, 3, 0); + req.setRequiredItems(Collections.singletonList(requiredBook)); + req.setTakeItems(true); + challenge.setRequirements(req); + + // Player holds an Unbreaking III book that was combined in an anvil (has repair_cost) + ItemStack anvilBook = createEnchantedBook(Enchantment.UNBREAKING, 3, 1); + assertFalse(anvilBook.isSimilar(requiredBook), "Sanity: strict isSimilar must differ on repair cost"); + when(inv.getContents()).thenReturn(new ItemStack[] { anvilBook }); + when(player.getInventory()).thenReturn(inv); + + assertTrue(TryToComplete.complete(addon, user, challenge, world, topLabel, permissionPrefix)); + verify(user, never()).getTranslation(any(World.class), eq("challenges.errors.not-enough-items"), any(), any()); + assertEquals(0, anvilBook.getAmount(), "The anvil-made book should have been taken"); + } + + @Test + void testInventoryChallengeEnchantedBookRequiredHasRepairCost() { + // Required item itself was created from an anvil-made book; player holds a clean one + InventoryRequirements req = new InventoryRequirements(); + ItemStack requiredBook = createEnchantedBook(Enchantment.UNBREAKING, 3, 2); + req.setRequiredItems(Collections.singletonList(requiredBook)); + challenge.setRequirements(req); + + ItemStack cleanBook = createEnchantedBook(Enchantment.UNBREAKING, 3, 0); + when(inv.getContents()).thenReturn(new ItemStack[] { cleanBook }); + when(player.getInventory()).thenReturn(inv); + + assertTrue(TryToComplete.complete(addon, user, challenge, world, topLabel, permissionPrefix)); + } + + @Test + void testInventoryChallengeEnchantedBookWrongLevelStillFails() { + // Ignoring repair cost must not loosen the enchantment check itself + InventoryRequirements req = new InventoryRequirements(); + ItemStack requiredBook = createEnchantedBook(Enchantment.UNBREAKING, 3, 0); + req.setRequiredItems(Collections.singletonList(requiredBook)); + challenge.setRequirements(req); + + ItemStack lowerBook = createEnchantedBook(Enchantment.UNBREAKING, 2, 1); + when(inv.getContents()).thenReturn(new ItemStack[] { lowerBook }); + when(player.getInventory()).thenReturn(inv); + // The "missing items" message prettifies the enchanted book, which needs vararg translations + Mockito.doAnswer(invocation -> invocation.getArgument(0, String.class)) + .when(user).getTranslationOrNothing(anyString(), Mockito.any(String[].class)); + + assertFalse(TryToComplete.complete(addon, user, challenge, world, topLabel, permissionPrefix)); + verify(user).getTranslation(any(World.class), eq("challenges.errors.not-enough-items"), eq("[items]"), + any()); + } + + @Test + void testUtilsIsSimilarIgnoringRepairCost() { + ItemStack clean = createEnchantedBook(Enchantment.UNBREAKING, 3, 0); + ItemStack anvil = createEnchantedBook(Enchantment.UNBREAKING, 3, 5); + ItemStack other = createEnchantedBook(Enchantment.MENDING, 1, 5); + + assertTrue(Utils.isSimilarIgnoringRepairCost(clean, anvil)); + assertTrue(Utils.isSimilarIgnoringRepairCost(anvil, clean)); + assertTrue(Utils.isSimilarIgnoringRepairCost(anvil, anvil.clone())); + assertFalse(Utils.isSimilarIgnoringRepairCost(anvil, other)); + assertFalse(Utils.isSimilarIgnoringRepairCost(null, clean)); + assertFalse(Utils.isSimilarIgnoringRepairCost(clean, null)); + + // The original item must not be modified + assertEquals(5, ((Repairable) anvil.getItemMeta()).getRepairCost()); + } + + @Test + void testUtilsWithoutRepairCost() { + ItemStack clean = createEnchantedBook(Enchantment.UNBREAKING, 3, 0); + ItemStack anvil = createEnchantedBook(Enchantment.UNBREAKING, 3, 5); + ItemStack plain = new ItemStack(Material.DIRT); + + // Items without a repair cost are returned as-is + assertTrue(clean == Utils.withoutRepairCost(clean)); + assertTrue(plain == Utils.withoutRepairCost(plain)); + assertNull(Utils.withoutRepairCost(null)); + + ItemStack stripped = Utils.withoutRepairCost(anvil); + assertFalse(((Repairable) stripped.getItemMeta()).hasRepairCost()); + assertTrue(stripped.isSimilar(clean)); + assertEquals(5, ((Repairable) anvil.getItemMeta()).getRepairCost(), "Original must be untouched"); + } + + @Test + void testGroupEqualItemsMergesAnvilBooks() { + ItemStack clean = createEnchantedBook(Enchantment.UNBREAKING, 3, 0); + ItemStack anvil = createEnchantedBook(Enchantment.UNBREAKING, 3, 3); + List grouped = Utils.groupEqualItems(Arrays.asList(clean, anvil), Set.of()); + assertEquals(1, grouped.size()); + assertEquals(2, grouped.get(0).getAmount()); + } }