Appearance
📬 AFU.Mailbox
ข้อมูลสคริปต์
- Resource:
AFU.Mailbox(v1.0.8) — ระบบกล่องจดหมาย / ส่งของขวัญให้ผู้เล่น - Framework: ESX Legacy (
es_extended) - Dependencies (จำเป็น):
- oxmysql
es_extended(ESX Legacy)
- Optional (ทางเลือก):
AFU.Notify— ใช้แทนระบบแจ้งเตือนภายใน (กรณีปิด Internal Notification)afu_log/nc_discordlogs— เปิดใช้เฉพาะเซิร์ฟเวอร์ที่มีระบบ Log เหล่านี้ (ถ้าไม่มีสคริปต์ทำงานได้ปกติ)
ข้อควรระวังเรื่องการแก้ไขไฟล์
- หาก Resource ของคุณมาพร้อมระบบ License ให้ใช้ Token/License ที่ได้รับจากผู้ขายเท่านั้น และติดต่อผู้ขาย (awayfromus.store) เมื่อเกิดปัญหา
- ให้แก้ไขเฉพาะไฟล์ในโฟลเดอร์
config/เท่านั้น
🛠️ Installation
1. Download & Placement
นำโฟลเดอร์ Resource ไปวางใน resources/ ของเซิร์ฟเวอร์
text
resources/
└── [afu]/
└── AFU.Mailbox/
├── config/
├── modules/
├── nui/
├── source/
└── fxmanifest.luaห้ามเปลี่ยนชื่อโฟลเดอร์
ต้องตั้งชื่อโฟลเดอร์ว่า AFU.Mailbox ตามตัวอย่าง ชื่อต้องมีจุด (.) ตรงตามนี้เสมอ เพราะระบบเรียกใช้งานผ่านชื่อ Resource จากสคริปต์อื่น เช่น exports['AFU.Mailbox'] หากเปลี่ยนชื่อ Command และ Export ทั้งหมดจะใช้งานไม่ได้
2. ตั้งค่า server.cfg
เพิ่มบรรทัดเหล่านี้ โดย ต้อง ensure oxmysql และ es_extended ก่อนเสมอ
cfg
ensure oxmysql
ensure es_extended
ensure AFU.Mailbox3. Database
ไม่ต้อง Import SQL เอง — เมื่อ Start Resource ครั้งแรก ระบบจะสร้าง Table ที่จำเป็นให้อัตโนมัติ 2 ตาราง:
| ตาราง | หน้าที่ |
|---|---|
afu_mails | เก็บเมลที่ส่งให้ผู้เล่นแต่ละคน (สถานะอ่าน/รับของ/ลบ) |
afu_mail_templates | เก็บเทมเพลตเมลที่แอดมินสร้าง (หัวเรื่อง, เนื้อหา, รางวัล) |
::: note เงื่อนไขการสร้าง Table อัตโนมัติ
- User ของ MySQL ที่ประกาศไว้ใน oxmysql ต้องมีสิทธิ์
CREATEในฐานข้อมูลของเซิร์ฟเวอร์ - ระบบใช้ตาราง
usersของ ESX ที่มีอยู่แล้วสำหรับการส่งเมลหาผู้เล่นแบบ Offline / ตามอาชีพ (ไม่ต้องสร้างเพิ่ม) :::
📋 โครงสร้าง Table (สำหรับผู้ที่ต้องการ Import เองเท่านั้น)
sql
CREATE TABLE IF NOT EXISTS `afu_mails` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`identifier` varchar(50) NOT NULL,
`mail_template_id` char(30) NOT NULL DEFAULT '',
`get_reward_at` timestamp NULL DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
`readed_at` timestamp NULL DEFAULT NULL,
`deleted_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
CREATE TABLE IF NOT EXISTS `afu_mail_templates` (
`id` char(30) NOT NULL DEFAULT '',
`title` varchar(255) NOT NULL DEFAULT 'UNTITLE',
`content` longtext NOT NULL,
`rewards` longtext NOT NULL DEFAULT '{}',
`created_by_identifier` varchar(50) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
`updated_at` timestamp NOT NULL DEFAULT current_timestamp(),
`deleted_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;4. Restart Server
Restart เซิร์ฟเวอร์ 1 ครั้ง แล้วตรวจสอบ Console ว่าไม่มี Error จาก AFU.Mailbox
⚙️ Configuration
ไฟล์ Config ที่ User แก้ไขได้มี 2 ไฟล์ อยู่ในโฟลเดอร์ config/:
| ไฟล์ | ใช้ทำอะไร |
|---|---|
config/system.config.lua | ตั้งค่าทั่วไป — รูปไอเทม, ประเภทของขวัญพิเศษ, การแจ้งเตือน |
config/server.functions.lua | ตั้งค่าฝั่งเซิร์ฟเวอร์ — กลุ่มแอดมิน, การมอบรางวัล, ระบบ Log |
🖼️ ตั้งค่ารูปไอเทม (system.config.lua)
Config.InventoryPath
| Type | string |
| Default | 'nui://inventory/web/assets/icons/' |
ที่อยู่โฟลเดอร์รูปภาพไอเทมที่ใช้แสดงในหน้า UI เมล ให้เปลี่ยนตาม Inventory ที่เซิร์ฟเวอร์ใช้งาน เช่น
lua
-- ตัวอย่าง
Config.InventoryPath = 'nui://inventory/web/assets/icons/' -- default inventory
Config.InventoryPath = 'nui://ox_inventory/web/images/' -- ox_inventoryWARNING
Path ต้องปิดท้ายด้วย / เสมอ และชื่อไฟล์รูปต้องตรงกับ spawn name ของไอเทม
Config.DefaultExtImage
| Type | string |
| Default | '.png' |
นามสกุลไฟล์รูปภาพเริ่มต้นของไอเทม เช่น .png, .webp
Config.OverrideImageExtImageItems
| Type | table<string, string> |
| Default | { ["weapon_box"] = ".gif" } |
กำหนดนามสกุลรูปเฉพาะตัวของไอเทมบางชิ้น (เช่น ไอเทมที่เป็นไฟล์ GIF)
lua
Config.OverrideImageExtImageItems = {
["weapon_box"] = ".gif",
["gift_special"] = ".webp", -- เพิ่มไอเทมอื่นได้ตามต้องการ
}Config.OverrideTypeItems
| Type | table<string, string> |
| Default | { ["weapon_box"] = "item" } |
บังคับชนิดการแสดงผลของไอเทมบางตัวในหน้า UI เช่น ให้ weapon_box แสดงเป็นไอเทมปกติ
🎁 ของขวัญแบบ Custom (AddOnItemsExecuteServerSide)
| Type | table[] (name, label, svExecFunc) |
| Default | มีตัวอย่าง new_player_item_set ให้ 1 รายการ |
ใช้สร้าง ของขวัญแบบกำหนดเอง ที่ไม่ใช่ไอเทม/เงินปกติ เมื่อผู้เล่นกดรับเมล ฟังก์ชัน svExecFunc จะทำงานฝั่งเซิร์ฟเวอร์ทันที และรายการนี้จะปรากฏเป็นตัวเลือกของขวัญในหน้า UI ของแอดมินด้วย
lua
Config.AddOnItemsExecuteServerSide = {
{
name = "new_player_item_set", -- ชื่ออ้างอิง (ห้ามซ้ำ, ห้ามมีช่องว่าง)
label = "ชุดไอเทมผู้เล่นใหม่", -- ชื่อที่แสดงใน UI
svExecFunc = function(source, identifier, xPlayer)
xPlayer.addInventoryItem('a_f_rod', 1)
xPlayer.addMoney(50000)
end
}
}| Field | Type | คำอธิบาย |
|---|---|---|
name | string | ชื่อ Key สำหรับอ้างอิง (ใช้ในระบบรางวัล) |
label | string | ชื่อที่แสดงในหน้า UI ของแอดมิน |
svExecFunc | function(source, identifier, xPlayer) | โค้ดที่ทำงานเมื่อผู้เล่นกดรับของ |
🔔 ตั้งค่าการแจ้งเตือน (Config.Notifications)
| ตัวแปร | Type | Default | คำอธิบาย |
|---|---|---|---|
useInternalNotification | boolean | true | true = ใช้ระบบแจ้งเตือนในตัวของเมลเมื่อมีเมลเข้า |
notifyTimeout | number | 5000 | ระยะเวลาแสดงผลแจ้งเตือน (มิลลิวินาที) |
ใช้ Notify ภายนอก (External Callback)
หากตั้ง useInternalNotification = false ระบบจะเรียก Callback 2 ตัวนี้แทน ให้แก้ไขข้างในให้เป็น Notify ของเซิร์ฟเวอร์คุณ (ค่าเริ่มต้นใช้ AFU.Notify):
| Callback | ได้รับค่า | ใช้เมื่อ |
|---|---|---|
Config.Notifications.ExternalCallbackAddMail(notificationItem) | { id, type, label, title } | มีเมลใหม่เข้ามาของผู้เล่น |
Config.Notifications.ExternalCallbackStatus(res) | { status: boolean, message: string } | แจ้งผลสำเร็จ/ผิดพลาดต่าง ๆ ของระบบ |
TIP
ถ้าไม่มี AFU.Notify ในเซิร์ฟเวอร์ ให้แก้เนื้อใน Callback เป็น Notify ของเซิร์ฟเวอร์คุณเอง (เช่น TriggerEvent('chat:addMessage', ...)) อย่าลบ Function ทิ้ง
👑 ตั้งค่าแอดมิน (server.functions.lua)
Functions.isAdmin(source)
| Return | boolean |
| Default | ผู้เล่นที่อยู่กลุ่ม ESX admin หรือ superadmin เท่านั้น |
ฟังก์ชันนี้ใช้ตรวจสิทธิ์ทั้งหมดของระบบเมล ได้แก่ การใช้ /mba, การสร้าง/แก้ไข/ลบเทมเพลต และการส่งเมล
lua
-- ตัวอย่าง: เพิ่มกลุ่ม mod ให้เป็นแอดมินของระบบเมลได้
return group == 'admin' or group == 'superadmin' or group == 'mod'DANGER
อย่าเปิดสิทธิ์กว้างเกินไป เพราะผู้ที่ผ่าน isAdmin สามารถ ส่งของ/เงินให้ผู้เล่นคนใดก็ได้ ผ่านหน้า UI
💰 การมอบรางวัล (Functions.OnAddItemsFromMailRewards)
เมื่อผู้เล่นกดรับของในเมล ระบบจะมอบรางวัลตามประเภทที่แอดมินตั้งไว้:
| ประเภทรางวัล (type) | การมอบให้ (ESX) | ตัวอย่าง name ที่ใช้ได้ |
|---|---|---|
item | xPlayer.addInventoryItem(name, count) | ไอเทมในตาราง items เช่น water, bread |
account | xPlayer.addAccountMoney(name, count) | money, bank, black_money |
exec-server-side | เรียกใช้ฟังก์ชันจาก Config.AddOnItemsExecuteServerSide | ชื่อ name ที่คุณสร้างเอง |
ภายในฟังก์ชันนี้มีจุดที่ปรับแต่งได้ดังนี้:
- Discord Log (ทางเลือก) — มีการเรียก
nc_discordlogsโดยมี Placeholder ให้ใส่ Webhook:
lua
exports.nc_discordlogs:Discord({
webhook = 'your_web_hook_key', -- 👈 เปลี่ยนเป็นชื่อ Webhook ของคุณ หรือ Comment บล็อกนี้ออกถ้าไม่ใช้
...
})WARNING
หากเซิร์ฟเวอร์ไม่มี nc_discordlogs หรือ afu_log ไม่ต้องตกใจ — โค้ดส่วนนี้ถูกป้องกัน Error ไว้แล้ว แต่ควร Comment ออกเพื่อความสะอาด และ อย่าปล่อยค่า your_web_hook_key ไว้ หากเปิดใช้ระบบ Log
- ลบเมลถาวรเมื่อรับของแล้ว (ทางเลือก) — ปกติเมลที่ลบจะถูกซ่อนไว้ในฐานข้อมูล หากต้องการให้ หายจาก Database ทันที เมื่อผู้เล่นกดรับของ ให้เปิดบรรทัดนี้ในไฟล์ Config:
lua
Queries.UnscopeDeleteMailByIds(mailIds)🎮 Usage
Commands
| Command | สิทธิ์ | คำอธิบาย |
|---|---|---|
/mbp | ผู้เล่นทุกคน | เปิดกล่องจดหมายของตัวเอง (อ่านเมล / รับของขวัญ / ลบเมล) |
/mba | Admin เท่านั้น | เปิดหน้าจัดการเมล (สร้างเทมเพลต / ส่งเมล) |
หน้าจอผู้เล่น (Mail Reader)
- ดูรายการเมลทั้งหมดที่ได้รับ พร้อมจุดแจ้งเตือนเมลที่ยังไม่ได้อ่าน
- เปิดอ่าน เมล — เนื้อหารองรับการจัดรูปแบบ HTML จาก Rich Text Editor
- รับของขวัญ ได้ทั้งทีละเมลหรือหลายเมลพร้อมกัน (เมลที่รับแล้วจะไม่รับซ้ำ)
- ลบเมล ออกจากกล่องจดหมาย
- เมื่อมีเมลเข้าใหม่ขณะออนไลน์ ระบบจะแจ้งเตือนทันที (พร้อมเสียงประกอบใน UI)
หน้าจอแอดมิน (Mail Sender)
- สร้างเทมเพลตเมล — ตั้งหัวเรื่อง, เนื้อหา (HTML), และแนบรางวัลได้หลายชิ้น (ไอเทม / เงิน / ของขวัญ Custom)
- บันทึกเทมเพลต ไว้ใช้ซ้ำ, แก้ไข หรือลบได้
- เลือกกลุ่มผู้รับ ได้หลายรูปแบบ:
| โหมด | คำอธิบาย |
|---|---|
| ส่งทุกคน | ผู้เล่นทุกคนทั้ง ออนไลน์และออฟไลน์ |
| ส่งผู้เล่นออนไลน์ทั้งหมด | เฉพาะผู้เล่นที่ออนไลน์ตอนนั้น |
| ส่งตามอาชีพ (Job) | ระบุชื่อ Job ได้หลายอัน ครอบคลุมผู้เล่นออฟไลน์ด้วย |
| สุ่มผู้เล่น N คน | สุ่มจากผู้เล่นที่ออนไลน์ |
| เลือกรายคน | ระบุ Server ID หรือ Steam Hex ได้ |
| พื้นที่รอบตัว (Radius) | ดึงวงเลือกพื้นที่รอบตัวแอดมิน แล้วส่งให้ผู้เล่นในวง |
🎯 ปุ่มควบคุมการเลือกพื้นที่ (Radius Picker)
| ปุ่ม | การทำงาน |
|---|---|
E | เพิ่มรัศมี |
Q | ลดรัศมี |
Shift (ค้าง) | ปรับรัศมีเร็วขึ้น |
Enter | ยืนยันพื้นที่ |
Backspace | ยกเลิก |
🔌 Exports (สำหรับ Developer)
ฝั่ง Server
exports.AFU.Mailbox:sendMailToPlayer(targetIds, mailTemplateId)
ส่งเมลให้ผู้เล่นจากสคริปต์อื่น (เช่น ระบบสมัครสมาชิก, Event, Shop)
lua
-- รับได้ทั้ง Server ID (number) และ Identifier (steam hex) ผสมกันได้ใน array เดียว
local targetIds = { 23, "steam:110000112345678" }
local mailTemplateId = "FGQLJFRQROFGEFZNMJAAXFUACUHELU"
exports.AFU.Mailbox:sendMailToPlayer(targetIds, mailTemplateId)| Parameter | Type | คำอธิบาย |
|---|---|---|
targetIds | table | Array ของ Server ID หรือ Identifier |
mailTemplateId | string | ID ของเทมเพลต (ดูได้จากหน้าจัดการเมลของแอดมิน) |
TIP
- ผู้เล่นที่ ออนไลน์ จะได้รับเมลและการแจ้งเตือนทันที
- ผู้เล่นที่ ออฟไลน์ ให้ส่งด้วย Steam Hex Identifier ระบบจะฝากเมลไว้ให้เมื่อกลับมา Online
mailTemplateIdต้องเป็นเทมเพลตที่ถูกสร้างไว้แล้วในระบบ (สร้างผ่าน/mba)
exports.AFU.Mailbox:isReady()
รอจนระบบเมลพร้อมทำงาน (เช่น ก่อนเรียก sendMailToPlayer ตอน Resource Start)
lua
exports['AFU.Mailbox']:isReady()ฝั่ง Client
exports['AFU.Mailbox']:openMailUI()
เปิดหน้ากล่องจดหมายของผู้เล่น (เหมือน /mbp) — เหมาะกับการผูกกับ Object/Marker ตู้ไปรษณีย์
lua
exports['AFU.Mailbox']:openMailUI()exports['AFU.Mailbox']:openAdminMailUI()
เปิดหน้าจัดการเมล (เหมือน /mba)
lua
exports['AFU.Mailbox']:openAdminMailUI()exports['AFU.Mailbox']:toggleMailboxInterface(mode)
สลับเปิด/ปิดหน้า UI แบบระบุโหมด
lua
exports['AFU.Mailbox']:toggleMailboxInterface("reader") -- หน้าผู้เล่น
exports['AFU.Mailbox']:toggleMailboxInterface("sender") -- หน้าแอดมิน (ต้องมีสิทธิ์)WARNING
การเรียก "sender" จากผู้เล่นที่ไม่มีสิทธิ์แอดมินจะถูก ปฏิเสธโดยอัตโนมัติ และฝั่งเซิร์ฟเวอร์ยังตรวจสิทธิ์ซ้ำอีกชั้น
🧰 Troubleshooting
| อาการ | สาเหตุที่พบบ่อย | วิธีแก้ |
|---|---|---|
พิมพ์ /mba แล้วไม่มีหน้าต่างเปิด | ผู้เล่นไม่ได้อยู่กลุ่ม admin / superadmin | เพิ่ม Group ผ่าน ESX หรือแก้ Functions.isAdmin() ตามหัวข้อ Configuration |
/mbp ไม่ตอบสนอง | Resource start ก่อน oxmysql / es_extended หรือ NUI โหลดไม่สำเร็จ | ตรวจ Order ของ ensure ใน server.cfg และดู Error ใน F8 Console / Server Console |
| มี Error เกี่ยวกับ MySQL ตอน Start | oxmysql ไม่ทำงาน, ฐานข้อมูลเชื่อมต่อไม่ได้ หรือ User ไม่มีสิทธิ์ CREATE | ตรวจ oxmysql ก่อน แล้วตรวจสิทธิ์ MySQL User |
| รูปไอเทมในเมลเป็นภาพเดียวกันหมด / ไม่ขึ้น | Config.InventoryPath ไม่ตรงกับ Inventory | แก้ Path และนามสกุลไฟล์ (DefaultExtImage, OverrideImageExtImageItems) ให้ถูกต้อง |
| กดรับของแล้วไม่ได้ไอเทม | ไม่มีชื่อไอเทมนั้นในตาราง items ของ ESX หรือชื่อ Account ผิด | เพิ่มไอเทมใน Database ก่อน และใช้ Account มาตรฐาน (money, bank, black_money) |
| ส่งเมลหาผู้เล่นออฟไลน์ไม่ถึง | ส่งด้วย Server ID ขณะที่ผู้เล่นออฟไลน์ | ใช้ Steam Hex Identifier แทน (เช่น steam:1100001xxxxxxxxx) |
| แจ้งเตือนเมลเข้าซ้ำหรือไม่ขึ้น | ตั้งทั้ง Internal และ External Notification พร้อมกัน | เลือกอย่างใดอย่างหนึ่ง: useInternalNotification = true หรือ ใช้ External Callback |
มี Error จาก nc_discordlogs / afu_log | เซิร์ฟเวอร์ไม่มีระบบ Log เหล่านี้ | Comment บล็อก Log ใน Functions.OnAddItemsFromMailRewards ออก |
| ลบ/แก้ไขเทมเพลตไม่ได้ | เทมเพลตถูกสร้างโดยแอดมินคนอื่น หรือสิทธิ์ไม่พอ | ระบบอนุญาตเฉพาะผู้ที่ผ่าน isAdmin เท่านั้น |
การขอ Support
หากยังแก้ปัญหาไม่ได้ ให้แนบ Console Log (F8) และ Server Console ที่มี Error ของ AFU.Mailbox พร้อมเวอร์ชัน Resource แจ้งผู้ขายได้ที่ awayfromus.store