feat: 指令界面配置
This commit is contained in:
parent
41203ae1c6
commit
52ca9cb066
|
|
@ -134,8 +134,7 @@ dependencies {
|
||||||
modImplementation("com.lowdragmc.ldlib:ldlib-forge-1.20.1:1.0.49") {
|
modImplementation("com.lowdragmc.ldlib:ldlib-forge-1.20.1:1.0.49") {
|
||||||
transitive = false
|
transitive = false
|
||||||
}
|
}
|
||||||
modImplementation("top.r3944realms.lib39:lib39:1.20.1-${lib39_version}")
|
modImplementation("top.r3944realms.lib39:lib39-forge-1.20.1:${lib39_version}")
|
||||||
implementation(jarJar("top.r3944realms.dg_lab.api:CommonApi:${dg_lab_version}"))
|
|
||||||
implementation(jarJar("top.r3944realms.dg_lab:Common:${dg_lab_version}"))
|
implementation(jarJar("top.r3944realms.dg_lab:Common:${dg_lab_version}"))
|
||||||
}
|
}
|
||||||
mixin {
|
mixin {
|
||||||
|
|
@ -255,11 +254,6 @@ publishing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================== 构建任务依赖 =====================
|
|
||||||
tasks.named('build') {
|
|
||||||
dependsOn sourceJar, apiSourceJar, apiJar, apiJavadocJar
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named('clean') {
|
tasks.named('clean') {
|
||||||
delete fileTree(dir: "${project.projectDir}/mcmodsrepo")
|
delete fileTree(dir: "${project.projectDir}/mcmodsrepo")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ mod_authors= R3944Realms, LeisureTimeDock
|
||||||
mod_description=Use DgLab PowerBox to improve Player's game sense.
|
mod_description=Use DgLab PowerBox to improve Player's game sense.
|
||||||
mod_credits=
|
mod_credits=
|
||||||
|
|
||||||
lib39_version=0.4.1
|
lib39_version=0.5.6
|
||||||
mutil_version=1.20.1-6.0.0
|
mutil_version=1.20.1-6.0.0
|
||||||
dg_lab_version=4.4.14.18
|
dg_lab_version=4.4.14.20
|
||||||
mutil_version_range=[6.0.0,]
|
mutil_version_range=[6.0.0,]
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
// 1.20.1 2026-03-08T19:34:45.1815278 Languages: zh_tw
|
// 1.20.1 2026-06-10T14:38:47.691308 Languages: zh_tw
|
||||||
4eb9507db96ec64d8176a664e22e36bf8763d09d assets/dglabgame/lang/zh_tw.json
|
de843a2665a924368d9ef5ba456d22eb7e24d89b assets/dglabgame/lang/zh_tw.json
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
// 1.20.1 2026-03-08T19:34:45.1719971 Languages: zh_cn
|
// 1.20.1 2026-06-10T14:38:47.6853295 Languages: zh_cn
|
||||||
9bb1075f2b018219335d8c3784d293cdd80464ac assets/dglabgame/lang/zh_cn.json
|
1fff14dbc8d8f08ca771484db1a902dbefbb4709 assets/dglabgame/lang/zh_cn.json
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
// 1.20.1 2026-03-08T19:34:45.1785204 Languages: lzh
|
// 1.20.1 2026-06-10T14:38:47.690311 Languages: lzh
|
||||||
41c40b3de74f63b246b0e67bbd74c5e220cd1e69 assets/dglabgame/lang/lzh.json
|
a51fc9b128855ce2e4ae7e81c861ec5a23681574 assets/dglabgame/lang/lzh.json
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
// 1.20.1 2026-03-08T19:34:45.1765211 Languages: en_us
|
// 1.20.1 2026-06-10T14:38:47.6883175 Languages: en_us
|
||||||
ca592519439edf564117cb3e2d7f98ae82defe15 assets/dglabgame/lang/en_us.json
|
543ea588d9607a5f1d99e220157eb42903c4f4a2 assets/dglabgame/lang/en_us.json
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,24 @@
|
||||||
{
|
{
|
||||||
|
"dglabgame.command.clear.sent": "Clear command sent for channel %s (%s target(s))",
|
||||||
|
"dglabgame.command.client.created": "DGLab client \"%s\" created (%s:%s)",
|
||||||
|
"dglabgame.command.client.list": "Registered clients: %s",
|
||||||
|
"dglabgame.command.client.none": "No DGLab clients registered",
|
||||||
|
"dglabgame.command.client.not_found": "Client \"%s\" not found",
|
||||||
|
"dglabgame.command.client.removed": "DGLab client \"%s\" removed",
|
||||||
|
"dglabgame.command.client.started": "DGLab client \"%s\" started",
|
||||||
|
"dglabgame.command.client.stopped": "DGLab client \"%s\" stopped",
|
||||||
|
"dglabgame.command.feedback.sent": "Feedback value %s sent to %s target(s)",
|
||||||
|
"dglabgame.command.invalid_channel": "Invalid channel. Use A or B.",
|
||||||
|
"dglabgame.command.invalid_policy": "Invalid policy. Use goto/set, increase/inc, or decrease/dec.",
|
||||||
|
"dglabgame.command.no_output": "No active DGLab output available. Start the server or a client first.",
|
||||||
|
"dglabgame.command.pulse.sent": "Pulse waveform sent to channel %s (%s target(s))",
|
||||||
|
"dglabgame.command.server.already_running": "DGLab server is already running",
|
||||||
|
"dglabgame.command.server.not_created": "DGLab server has not been created yet",
|
||||||
|
"dglabgame.command.server.not_running": "DGLab server is not running",
|
||||||
|
"dglabgame.command.server.started": "DGLab WebSocket server started on port %s",
|
||||||
|
"dglabgame.command.server.status": "Server status: %s, connected apps: %s",
|
||||||
|
"dglabgame.command.server.stopped": "DGLab server stopped",
|
||||||
|
"dglabgame.command.strength.sent": "Strength [%s %s %s] sent to %s target(s)",
|
||||||
"dglabgame.name": "DG Lab Game",
|
"dglabgame.name": "DG Lab Game",
|
||||||
"dglabgame.user_agreement.accept": "§2§lAccept",
|
"dglabgame.user_agreement.accept": "§2§lAccept",
|
||||||
"dglabgame.user_agreement.line1": "1. This mod is developed by §e§lR3944Realms §r, completely free and open source.",
|
"dglabgame.user_agreement.line1": "1. This mod is developed by §e§lR3944Realms §r, completely free and open source.",
|
||||||
|
|
@ -8,6 +28,22 @@
|
||||||
"dglabgame.user_agreement.line5": "5. §4Prohibited for any illegal or immoral activities.",
|
"dglabgame.user_agreement.line5": "5. §4Prohibited for any illegal or immoral activities.",
|
||||||
"dglabgame.user_agreement.line6": "6. §4Developers are not responsible for any personal injury or property damage.",
|
"dglabgame.user_agreement.line6": "6. §4Developers are not responsible for any personal injury or property damage.",
|
||||||
"dglabgame.user_agreement.refuse": "§4§lRefuse",
|
"dglabgame.user_agreement.refuse": "§4§lRefuse",
|
||||||
|
"dglabgame.user_agreement.reject_use": "Not agreed to user guidelines, usage rejected",
|
||||||
|
"gui.dglabgame.client.label": "Client:",
|
||||||
|
"gui.dglabgame.feedback.send": "Send Feedback:",
|
||||||
|
"gui.dglabgame.qrcode.copy": "Copy QR URL to clipboard",
|
||||||
|
"gui.dglabgame.server.max_conn": "Max:",
|
||||||
|
"gui.dglabgame.server.port": "Port:",
|
||||||
|
"gui.dglabgame.server.status": "Status: %s",
|
||||||
|
"gui.dglabgame.strength.channel_a": "Channel A",
|
||||||
|
"gui.dglabgame.strength.channel_b": "Channel B",
|
||||||
|
"gui.dglabgame.tab.feedback": "Feedback",
|
||||||
|
"gui.dglabgame.tab.qrcode": "QR Code",
|
||||||
|
"gui.dglabgame.tab.server": "Server",
|
||||||
|
"gui.dglabgame.tab.strength": "Strength",
|
||||||
|
"gui.dglabgame.tab.waveform": "Waveform",
|
||||||
|
"gui.dglabgame.waveform.channel": "Channel:",
|
||||||
"key.categories.dglabgame": "DG Lab Game",
|
"key.categories.dglabgame": "DG Lab Game",
|
||||||
|
"key.dglabgame.management": "Open Management",
|
||||||
"key.dglabgame.test": "Test"
|
"key.dglabgame.test": "Test"
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,24 @@
|
||||||
{
|
{
|
||||||
|
"dglabgame.command.clear.sent": "清除之令已送至通道 %s (%s 標的)",
|
||||||
|
"dglabgame.command.client.created": "DGLab 客戶 \"%s\" 已建 (%s:%s)",
|
||||||
|
"dglabgame.command.client.list": "已註客戶: %s",
|
||||||
|
"dglabgame.command.client.none": "無已註之 DGLab 客戶",
|
||||||
|
"dglabgame.command.client.not_found": "未見客戶 \"%s\"",
|
||||||
|
"dglabgame.command.client.removed": "DGLab 客戶 \"%s\" 已除",
|
||||||
|
"dglabgame.command.client.started": "DGLab 客戶 \"%s\" 已啟",
|
||||||
|
"dglabgame.command.client.stopped": "DGLab 客戶 \"%s\" 已停",
|
||||||
|
"dglabgame.command.feedback.sent": "回應值 %s 已送至 %s 標的",
|
||||||
|
"dglabgame.command.invalid_channel": "通道有誤,當用 A 或 B。",
|
||||||
|
"dglabgame.command.invalid_policy": "策略有誤,當用 goto/set、increase/inc 或 decrease/dec。",
|
||||||
|
"dglabgame.command.no_output": "無可用之 DGLab 輸出。請先啟伺服器或客戶。",
|
||||||
|
"dglabgame.command.pulse.sent": "脈衝波形已送至通道 %s (%s 標的)",
|
||||||
|
"dglabgame.command.server.already_running": "DGLab 伺服器已在運作中",
|
||||||
|
"dglabgame.command.server.not_created": "DGLab 伺服器尚未建",
|
||||||
|
"dglabgame.command.server.not_running": "DGLab 伺服器未啟",
|
||||||
|
"dglabgame.command.server.started": "DGLab WebSocket 伺服器已於埠 %s 啟",
|
||||||
|
"dglabgame.command.server.status": "伺服器態: %s, 已連應用: %s",
|
||||||
|
"dglabgame.command.server.stopped": "DGLab 伺服器已停",
|
||||||
|
"dglabgame.command.strength.sent": "強度 [%s %s %s] 已送至 %s 標的",
|
||||||
"dglabgame.name": "郊狼戯",
|
"dglabgame.name": "郊狼戯",
|
||||||
"dglabgame.user_agreement.accept": "§2§l認",
|
"dglabgame.user_agreement.accept": "§2§l認",
|
||||||
"dglabgame.user_agreement.line1": "1. 本模組乃 §e§lR3944Realms §r 所製,全然免費而開源。",
|
"dglabgame.user_agreement.line1": "1. 本模組乃 §e§lR3944Realms §r 所製,全然免費而開源。",
|
||||||
|
|
@ -8,6 +28,22 @@
|
||||||
"dglabgame.user_agreement.line5": "5. §4禁作非法不德之事。",
|
"dglabgame.user_agreement.line5": "5. §4禁作非法不德之事。",
|
||||||
"dglabgame.user_agreement.line6": "6. §4凡人身之傷、財物之損,開發者概不負責。",
|
"dglabgame.user_agreement.line6": "6. §4凡人身之傷、財物之損,開發者概不負責。",
|
||||||
"dglabgame.user_agreement.refuse": "§4§l否",
|
"dglabgame.user_agreement.refuse": "§4§l否",
|
||||||
|
"dglabgame.user_agreement.reject_use": "未允用戶之約,拒用",
|
||||||
|
"gui.dglabgame.client.label": "客戶:",
|
||||||
|
"gui.dglabgame.feedback.send": "發回應:",
|
||||||
|
"gui.dglabgame.qrcode.copy": "複QR URL",
|
||||||
|
"gui.dglabgame.server.max_conn": "至多:",
|
||||||
|
"gui.dglabgame.server.port": "埠:",
|
||||||
|
"gui.dglabgame.server.status": "態: %s",
|
||||||
|
"gui.dglabgame.strength.channel_a": "通道甲",
|
||||||
|
"gui.dglabgame.strength.channel_b": "通道乙",
|
||||||
|
"gui.dglabgame.tab.feedback": "回應",
|
||||||
|
"gui.dglabgame.tab.qrcode": "二維碼",
|
||||||
|
"gui.dglabgame.tab.server": "伺服器",
|
||||||
|
"gui.dglabgame.tab.strength": "強度",
|
||||||
|
"gui.dglabgame.tab.waveform": "波形",
|
||||||
|
"gui.dglabgame.waveform.channel": "通道:",
|
||||||
"key.categories.dglabgame": "郊狼戯",
|
"key.categories.dglabgame": "郊狼戯",
|
||||||
|
"key.dglabgame.management": "啟管理",
|
||||||
"key.dglabgame.test": "式"
|
"key.dglabgame.test": "式"
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,24 @@
|
||||||
{
|
{
|
||||||
|
"dglabgame.command.clear.sent": "清除指令已发送至通道 %s (%s 个目标)",
|
||||||
|
"dglabgame.command.client.created": "DGLab 客户端 \"%s\" 已创建 (%s:%s)",
|
||||||
|
"dglabgame.command.client.list": "已注册的客户端: %s",
|
||||||
|
"dglabgame.command.client.none": "没有已注册的 DGLab 客户端",
|
||||||
|
"dglabgame.command.client.not_found": "未找到客户端 \"%s\"",
|
||||||
|
"dglabgame.command.client.removed": "DGLab 客户端 \"%s\" 已移除",
|
||||||
|
"dglabgame.command.client.started": "DGLab 客户端 \"%s\" 已启动",
|
||||||
|
"dglabgame.command.client.stopped": "DGLab 客户端 \"%s\" 已关闭",
|
||||||
|
"dglabgame.command.feedback.sent": "反馈值 %s 已发送至 %s 个目标",
|
||||||
|
"dglabgame.command.invalid_channel": "无效的通道。请使用 A 或 B。",
|
||||||
|
"dglabgame.command.invalid_policy": "无效的策略。请使用 goto/set, increase/inc 或 decrease/dec。",
|
||||||
|
"dglabgame.command.no_output": "没有可用的 DGLab 输出。请先启动服务器或客户端。",
|
||||||
|
"dglabgame.command.pulse.sent": "脉冲波形已发送至通道 %s (%s 个目标)",
|
||||||
|
"dglabgame.command.server.already_running": "DGLab 服务器已在运行中",
|
||||||
|
"dglabgame.command.server.not_created": "DGLab 服务器尚未创建",
|
||||||
|
"dglabgame.command.server.not_running": "DGLab 服务器未在运行",
|
||||||
|
"dglabgame.command.server.started": "DGLab WebSocket 服务器已在端口 %s 启动",
|
||||||
|
"dglabgame.command.server.status": "服务器状态: %s, 已连接应用: %s",
|
||||||
|
"dglabgame.command.server.stopped": "DGLab 服务器已关闭",
|
||||||
|
"dglabgame.command.strength.sent": "强度 [%s %s %s] 已发送至 %s 个目标",
|
||||||
"dglabgame.name": "郊狼游戏",
|
"dglabgame.name": "郊狼游戏",
|
||||||
"dglabgame.user_agreement.accept": "§2§l接受",
|
"dglabgame.user_agreement.accept": "§2§l接受",
|
||||||
"dglabgame.user_agreement.line1": "1. 本模组由 §e§lR3944Realms §r开发,完全免费开源。",
|
"dglabgame.user_agreement.line1": "1. 本模组由 §e§lR3944Realms §r开发,完全免费开源。",
|
||||||
|
|
@ -8,6 +28,22 @@
|
||||||
"dglabgame.user_agreement.line5": "5. §4禁止用于任何违法或不道德的活动。",
|
"dglabgame.user_agreement.line5": "5. §4禁止用于任何违法或不道德的活动。",
|
||||||
"dglabgame.user_agreement.line6": "6. §4开发者不对任何人身伤害或财产损失负责。",
|
"dglabgame.user_agreement.line6": "6. §4开发者不对任何人身伤害或财产损失负责。",
|
||||||
"dglabgame.user_agreement.refuse": "§4§l拒绝",
|
"dglabgame.user_agreement.refuse": "§4§l拒绝",
|
||||||
|
"dglabgame.user_agreement.reject_use": "未同意用户使用准则,拒绝使用",
|
||||||
|
"gui.dglabgame.client.label": "客户端:",
|
||||||
|
"gui.dglabgame.feedback.send": "发送反馈:",
|
||||||
|
"gui.dglabgame.qrcode.copy": "复制QR URL到剪贴板",
|
||||||
|
"gui.dglabgame.server.max_conn": "最大:",
|
||||||
|
"gui.dglabgame.server.port": "端口:",
|
||||||
|
"gui.dglabgame.server.status": "状态: %s",
|
||||||
|
"gui.dglabgame.strength.channel_a": "通道A",
|
||||||
|
"gui.dglabgame.strength.channel_b": "通道B",
|
||||||
|
"gui.dglabgame.tab.feedback": "反馈",
|
||||||
|
"gui.dglabgame.tab.qrcode": "二维码",
|
||||||
|
"gui.dglabgame.tab.server": "服务器",
|
||||||
|
"gui.dglabgame.tab.strength": "强度",
|
||||||
|
"gui.dglabgame.tab.waveform": "波形",
|
||||||
|
"gui.dglabgame.waveform.channel": "通道:",
|
||||||
"key.categories.dglabgame": "郊狼游戏",
|
"key.categories.dglabgame": "郊狼游戏",
|
||||||
|
"key.dglabgame.management": "打开管理",
|
||||||
"key.dglabgame.test": "测试"
|
"key.dglabgame.test": "测试"
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,24 @@
|
||||||
{
|
{
|
||||||
|
"dglabgame.command.clear.sent": "清除指令已傳送至通道 %s (%s 個目標)",
|
||||||
|
"dglabgame.command.client.created": "DGLab 客戶端 \"%s\" 已創建 (%s:%s)",
|
||||||
|
"dglabgame.command.client.list": "已註冊的客戶端: %s",
|
||||||
|
"dglabgame.command.client.none": "沒有已註冊的 DGLab 客戶端",
|
||||||
|
"dglabgame.command.client.not_found": "未找到客戶端 \"%s\"",
|
||||||
|
"dglabgame.command.client.removed": "DGLab 客戶端 \"%s\" 已移除",
|
||||||
|
"dglabgame.command.client.started": "DGLab 客戶端 \"%s\" 已啟動",
|
||||||
|
"dglabgame.command.client.stopped": "DGLab 客戶端 \"%s\" 已關閉",
|
||||||
|
"dglabgame.command.feedback.sent": "回饋值 %s 已傳送至 %s 個目標",
|
||||||
|
"dglabgame.command.invalid_channel": "無效的通道。請使用 A 或 B。",
|
||||||
|
"dglabgame.command.invalid_policy": "無效的策略。請使用 goto/set, increase/inc 或 decrease/dec。",
|
||||||
|
"dglabgame.command.no_output": "沒有可用的 DGLab 輸出。請先啟動伺服器或客戶端。",
|
||||||
|
"dglabgame.command.pulse.sent": "脈衝波形已傳送至通道 %s (%s 個目標)",
|
||||||
|
"dglabgame.command.server.already_running": "DGLab 伺服器已在執行中",
|
||||||
|
"dglabgame.command.server.not_created": "DGLab 伺服器尚未創建",
|
||||||
|
"dglabgame.command.server.not_running": "DGLab 伺服器未在執行",
|
||||||
|
"dglabgame.command.server.started": "DGLab WebSocket 伺服器已在連接埠 %s 啟動",
|
||||||
|
"dglabgame.command.server.status": "伺服器狀態: %s, 已連線應用: %s",
|
||||||
|
"dglabgame.command.server.stopped": "DGLab 伺服器已關閉",
|
||||||
|
"dglabgame.command.strength.sent": "強度 [%s %s %s] 已傳送至 %s 個目標",
|
||||||
"dglabgame.name": "郊狼游戲",
|
"dglabgame.name": "郊狼游戲",
|
||||||
"dglabgame.user_agreement.accept": "§2§l接受",
|
"dglabgame.user_agreement.accept": "§2§l接受",
|
||||||
"dglabgame.user_agreement.line1": "1. 本模組由 §e§lR3944Realms §r 開發,完全免費開源。",
|
"dglabgame.user_agreement.line1": "1. 本模組由 §e§lR3944Realms §r 開發,完全免費開源。",
|
||||||
|
|
@ -8,6 +28,22 @@
|
||||||
"dglabgame.user_agreement.line5": "5. §4禁止用於任何違法或不道德之活動。",
|
"dglabgame.user_agreement.line5": "5. §4禁止用於任何違法或不道德之活動。",
|
||||||
"dglabgame.user_agreement.line6": "6. §4開發者不對任何人身份害或財產損失負責。",
|
"dglabgame.user_agreement.line6": "6. §4開發者不對任何人身份害或財產損失負責。",
|
||||||
"dglabgame.user_agreement.refuse": "§4§l拒絕",
|
"dglabgame.user_agreement.refuse": "§4§l拒絕",
|
||||||
|
"dglabgame.user_agreement.reject_use": "未同意使用者準則,拒絕使用",
|
||||||
|
"gui.dglabgame.client.label": "客戶端:",
|
||||||
|
"gui.dglabgame.feedback.send": "發送回饋:",
|
||||||
|
"gui.dglabgame.qrcode.copy": "複製QR URL到剪貼板",
|
||||||
|
"gui.dglabgame.server.max_conn": "最大:",
|
||||||
|
"gui.dglabgame.server.port": "連接埠:",
|
||||||
|
"gui.dglabgame.server.status": "狀態: %s",
|
||||||
|
"gui.dglabgame.strength.channel_a": "通道A",
|
||||||
|
"gui.dglabgame.strength.channel_b": "通道B",
|
||||||
|
"gui.dglabgame.tab.feedback": "回饋",
|
||||||
|
"gui.dglabgame.tab.qrcode": "QR碼",
|
||||||
|
"gui.dglabgame.tab.server": "伺服器",
|
||||||
|
"gui.dglabgame.tab.strength": "強度",
|
||||||
|
"gui.dglabgame.tab.waveform": "波形",
|
||||||
|
"gui.dglabgame.waveform.channel": "通道:",
|
||||||
"key.categories.dglabgame": "郊狼游戲",
|
"key.categories.dglabgame": "郊狼游戲",
|
||||||
|
"key.dglabgame.management": "開啟管理",
|
||||||
"key.dglabgame.test": "测试"
|
"key.dglabgame.test": "测试"
|
||||||
}
|
}
|
||||||
|
|
@ -3,10 +3,14 @@ package top.leisuretimedock.dglabgame;
|
||||||
import com.mojang.logging.LogUtils;
|
import com.mojang.logging.LogUtils;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraftforge.fml.ModList;
|
import net.minecraftforge.fml.ModList;
|
||||||
|
import net.minecraftforge.fml.ModLoadingContext;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
import net.minecraftforge.fml.config.ModConfig;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
import top.leisuretimedock.dglabgame.config.ClientConfig;
|
||||||
|
import top.leisuretimedock.dglabgame.config.CommonConfig;
|
||||||
import top.leisuretimedock.dglabgame.core.network.DLGNetworkHandler;
|
import top.leisuretimedock.dglabgame.core.network.DLGNetworkHandler;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -19,6 +23,8 @@ public class DGLabGame {
|
||||||
}
|
}
|
||||||
public DGLabGame() {
|
public DGLabGame() {
|
||||||
DLGNetworkHandler.register();
|
DLGNetworkHandler.register();
|
||||||
|
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, CommonConfig.SPEC);
|
||||||
|
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ClientConfig.SPEC);
|
||||||
}
|
}
|
||||||
@Contract("_ -> new")
|
@Contract("_ -> new")
|
||||||
public static @NotNull ResourceLocation rl(String path) {
|
public static @NotNull ResourceLocation rl(String path) {
|
||||||
|
|
|
||||||
|
|
@ -15,4 +15,12 @@ public class DLGKeyMapping {
|
||||||
GLFW.GLFW_KEY_Z,
|
GLFW.GLFW_KEY_Z,
|
||||||
"key.categories.dglabgame"
|
"key.categories.dglabgame"
|
||||||
);
|
);
|
||||||
|
public static final KeyMapping KEY_MANAGEMENT = new KeyMapping(
|
||||||
|
"key.dglabgame.management",
|
||||||
|
KeyConflictContext.IN_GAME,
|
||||||
|
KeyModifier.NONE,
|
||||||
|
InputConstants.Type.KEYSYM,
|
||||||
|
GLFW.GLFW_KEY_M,
|
||||||
|
"key.categories.dglabgame"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,11 @@ import com.lowdragmc.lowdraglib.gui.widget.Widget;
|
||||||
import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup;
|
import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import top.leisuretimedock.dglabgame.config.CommonConfig;
|
||||||
import top.leisuretimedock.dglabgame.core.network.DLGNetworkHandler;
|
import top.leisuretimedock.dglabgame.core.network.DLGNetworkHandler;
|
||||||
import top.leisuretimedock.dglabgame.core.network.toServer.AcceptUserAgreementPacket;
|
import top.leisuretimedock.dglabgame.core.network.toServer.AcceptUserAgreementPacket;
|
||||||
import top.leisuretimedock.dglabgame.util.UILoader;
|
import top.leisuretimedock.dglabgame.util.UILoader;
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
@ -26,11 +26,11 @@ public class ConfirmGui implements ILdlibGui {
|
||||||
widgetGroup.ifPresent(group -> {
|
widgetGroup.ifPresent(group -> {
|
||||||
Widget yes = group.getFirstWidgetById("yes");
|
Widget yes = group.getFirstWidgetById("yes");
|
||||||
if (yes instanceof ButtonWidget yesButton) {
|
if (yes instanceof ButtonWidget yesButton) {
|
||||||
ImageWidget imageWidget = new ImageWidget(yesButton.getPositionX() + 3, yesButton.getPositionY() + 3, yesButton.getSizeWidth() - 6, yesButton.getSizeHeight() - 6, new ColorRectTexture(Color.DARK_GRAY));
|
ImageWidget imageWidget = new ImageWidget(yesButton.getPositionX() + 3, yesButton.getPositionY() + 3, yesButton.getSizeWidth() - 6, yesButton.getSizeHeight() - 6, new ColorRectTexture(0xff373737));
|
||||||
group.addWidget(imageWidget);
|
group.addWidget(imageWidget);
|
||||||
yesButton.setActive(false);
|
yesButton.setActive(false);
|
||||||
Timer timer = new Timer();
|
Timer timer = new Timer();
|
||||||
final int[] countdown = {5};
|
final int[] countdown = {CommonConfig.COUNTDOWN_SECONDS.get()};
|
||||||
timer.scheduleAtFixedRate(
|
timer.scheduleAtFixedRate(
|
||||||
new TimerTask() {
|
new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,374 @@
|
||||||
|
package top.leisuretimedock.dglabgame.client.gui;
|
||||||
|
|
||||||
|
import com.lowdragmc.lowdraglib.gui.texture.ColorRectTexture;
|
||||||
|
import com.lowdragmc.lowdraglib.gui.texture.ResourceBorderTexture;
|
||||||
|
import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture;
|
||||||
|
import com.lowdragmc.lowdraglib.gui.texture.TextTexture;
|
||||||
|
import com.lowdragmc.lowdraglib.gui.widget.*;
|
||||||
|
import com.r3944realms.dg_lab.api.manager.Status;
|
||||||
|
import com.r3944realms.dg_lab.api.message.IPowerBoxMsg;
|
||||||
|
import com.r3944realms.dg_lab.api.message.argType.Channel;
|
||||||
|
import com.r3944realms.dg_lab.api.message.argType.ChangePolicy;
|
||||||
|
import com.r3944realms.dg_lab.api.message.data.PulseWaveListGenerator;
|
||||||
|
import com.r3944realms.dg_lab.api.websocket.message.MessageDirection;
|
||||||
|
import com.r3944realms.dg_lab.api.websocket.message.PowerBoxMessage;
|
||||||
|
import com.r3944realms.dg_lab.manager.DGPBClientManager;
|
||||||
|
import com.r3944realms.dg_lab.websocket.sharedData.ClientPowerBoxSharedData;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import top.leisuretimedock.dglabgame.config.ClientConfig;
|
||||||
|
import top.leisuretimedock.dglabgame.config.CommonConfig;
|
||||||
|
import top.leisuretimedock.dglabgame.core.manager.DGLabManagerHolder;
|
||||||
|
import top.leisuretimedock.dglabgame.core.manager.ServerManager;
|
||||||
|
import top.leisuretimedock.dglabgame.core.network.DLGNetworkHandler;
|
||||||
|
import top.leisuretimedock.dglabgame.core.network.toServer.UpdateServerConfigPacket;
|
||||||
|
import top.leisuretimedock.dglabgame.core.network.toServer.UpdateStrengthConfigPacket;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.datatransfer.StringSelection;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public class DGLabManagementGui implements ILdlibGui {
|
||||||
|
private static final int W = 380;
|
||||||
|
private static final int H = 260;
|
||||||
|
private static final String CLIENT_ID = "dglabgame-gui";
|
||||||
|
private String currentPage = "qrcode";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WidgetGroup createGui() {
|
||||||
|
WidgetGroup root = new WidgetGroup(0, 0, W, H);
|
||||||
|
root.setBackground(new ColorRectTexture(0xff1a1a1a));
|
||||||
|
|
||||||
|
// top nav bar
|
||||||
|
root.addWidget(navButton("qrcode", 5, 5, 55, 18, "gui.dglabgame.tab.qrcode"));
|
||||||
|
root.addWidget(navButton("strength", 65, 5, 55, 18, "gui.dglabgame.tab.strength"));
|
||||||
|
root.addWidget(navButton("waveform", 125, 5, 55, 18, "gui.dglabgame.tab.waveform"));
|
||||||
|
root.addWidget(navButton("feedback", 185, 5, 55, 18, "gui.dglabgame.tab.feedback"));
|
||||||
|
|
||||||
|
boolean isAdmin = Minecraft.getInstance().player != null
|
||||||
|
&& Minecraft.getInstance().player.hasPermissions(4);
|
||||||
|
if (isAdmin) {
|
||||||
|
root.addWidget(navButton("server", 245, 5, 55, 18, "gui.dglabgame.tab.server"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// content area
|
||||||
|
root.addWidget(buildContentArea());
|
||||||
|
|
||||||
|
// bottom bar: client selector
|
||||||
|
root.addWidget(buildBottomBar());
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ButtonWidget navButton(String page, int x, int y, int w, int h, String langKey) {
|
||||||
|
ButtonWidget btn = new ButtonWidget(x, y, w, h,
|
||||||
|
new TextTexture(Component.translatable(langKey).getString(), 0xffffffff),
|
||||||
|
cd -> switchPage(page)
|
||||||
|
);
|
||||||
|
btn.setBackground(new ColorRectTexture(page.equals(currentPage) ? 0xff4444aa : 0xff333333));
|
||||||
|
return btn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchPage(String page) {
|
||||||
|
currentPage = page;
|
||||||
|
display();
|
||||||
|
}
|
||||||
|
|
||||||
|
private WidgetGroup buildContentArea() {
|
||||||
|
WidgetGroup area = new WidgetGroup(5, 28, W - 10, H - 62);
|
||||||
|
area.setBackground(new ColorRectTexture(0xff222222));
|
||||||
|
|
||||||
|
switch (currentPage) {
|
||||||
|
case "qrcode": buildQrCodeTab(area); break;
|
||||||
|
case "strength": buildStrengthTab(area); break;
|
||||||
|
case "waveform": buildWaveformTab(area); break;
|
||||||
|
case "feedback": buildFeedbackTab(area); break;
|
||||||
|
case "server": buildServerTab(area); break;
|
||||||
|
}
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== QR Code Tab ====================
|
||||||
|
|
||||||
|
private void buildQrCodeTab(WidgetGroup group) {
|
||||||
|
int y = 10;
|
||||||
|
TextFieldWidget urlField = new TextFieldWidget(10, y, W - 40, 15, () -> "", s -> {});
|
||||||
|
urlField.setCurrentString("");
|
||||||
|
urlField.setBordered(true);
|
||||||
|
group.addWidget(urlField);
|
||||||
|
|
||||||
|
group.addWidget(new ButtonWidget(W - 45, y, 22, 15, cd -> {
|
||||||
|
String url = getQrCodeUrl();
|
||||||
|
Toolkit.getDefaultToolkit().getSystemClipboard()
|
||||||
|
.setContents(new StringSelection(url), null);
|
||||||
|
}).setBackground(new ColorRectTexture(0xff336633)));
|
||||||
|
|
||||||
|
y += 22;
|
||||||
|
group.addWidget(new ImageWidget(10, y, W - 40, 14,
|
||||||
|
new TextTexture(Component.translatable("gui.dglabgame.qrcode.copy").getString(), 0xffaaaaaa)));
|
||||||
|
|
||||||
|
y += 20;
|
||||||
|
var names = DGLabManagerHolder.getClientManager().getClientNames();
|
||||||
|
for (String name : names) {
|
||||||
|
group.addWidget(new ImageWidget(10, y, W - 40, 10,
|
||||||
|
new TextTexture(name, 0xffcccccc)));
|
||||||
|
y += 14;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getQrCodeUrl() {
|
||||||
|
var names = DGLabManagerHolder.getClientManager().getClientNames();
|
||||||
|
for (String name : names) {
|
||||||
|
Optional<DGPBClientManager> client = DGLabManagerHolder.getClientManager().getClient(name);
|
||||||
|
if (client.isPresent()) {
|
||||||
|
ClientPowerBoxSharedData sd = client.get().getSharedData();
|
||||||
|
if (sd != null && sd.rqCodeUrl != null && !sd.rqCodeUrl.isEmpty()) {
|
||||||
|
return sd.rqCodeUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Strength Tab ====================
|
||||||
|
|
||||||
|
private void buildStrengthTab(WidgetGroup group) {
|
||||||
|
int y = 8;
|
||||||
|
group.addWidget(new ImageWidget(10, y, 60, 10,
|
||||||
|
new TextTexture(Component.translatable("gui.dglabgame.strength.channel_a").getString(), 0xffff4444)));
|
||||||
|
|
||||||
|
y += 14;
|
||||||
|
group.addWidget(strengthField("maxA", W / 2 - 55, y, CommonConfig.MAX_STRENGTH_A.get()));
|
||||||
|
group.addWidget(strengthField("minA", W / 2 + 15, y, CommonConfig.MIN_STRENGTH_A.get()));
|
||||||
|
|
||||||
|
y += 20;
|
||||||
|
group.addWidget(new ImageWidget(10, y, 60, 10,
|
||||||
|
new TextTexture(Component.translatable("gui.dglabgame.strength.channel_b").getString(), 0xff4444ff)));
|
||||||
|
|
||||||
|
y += 14;
|
||||||
|
group.addWidget(strengthField("maxB", W / 2 - 55, y, CommonConfig.MAX_STRENGTH_B.get()));
|
||||||
|
group.addWidget(strengthField("minB", W / 2 + 15, y, CommonConfig.MIN_STRENGTH_B.get()));
|
||||||
|
|
||||||
|
y += 22;
|
||||||
|
group.addWidget(new ButtonWidget(W / 2 - 30, y, 60, 16, cd -> {
|
||||||
|
TextFieldWidget maxAF = (TextFieldWidget) group.getFirstWidgetById("maxA");
|
||||||
|
TextFieldWidget minAF = (TextFieldWidget) group.getFirstWidgetById("minA");
|
||||||
|
TextFieldWidget maxBF = (TextFieldWidget) group.getFirstWidgetById("maxB");
|
||||||
|
TextFieldWidget minBF = (TextFieldWidget) group.getFirstWidgetById("minB");
|
||||||
|
try {
|
||||||
|
int maxA = Integer.parseInt(maxAF.getCurrentString());
|
||||||
|
int minA = Integer.parseInt(minAF.getCurrentString());
|
||||||
|
int maxB = Integer.parseInt(maxBF.getCurrentString());
|
||||||
|
int minB = Integer.parseInt(minBF.getCurrentString());
|
||||||
|
DLGNetworkHandler.CHANNEL.sendToServer(new UpdateStrengthConfigPacket(maxA, minA, maxB, minB));
|
||||||
|
} catch (NumberFormatException ignored) {}
|
||||||
|
}).setBackground(new ColorRectTexture(0xff336633)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextFieldWidget strengthField(String id, int x, int y, int value) {
|
||||||
|
TextFieldWidget field = new TextFieldWidget(x, y, 50, 14, () -> "", s -> {});
|
||||||
|
field.setCurrentString(String.valueOf(value));
|
||||||
|
field.setBordered(true);
|
||||||
|
field.setId(id);
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Waveform Tab ====================
|
||||||
|
|
||||||
|
private void buildWaveformTab(WidgetGroup group) {
|
||||||
|
int y = 8;
|
||||||
|
String[] labels = {"f1", "s1", "f2", "s2", "f3", "s3", "f4", "s4"};
|
||||||
|
int[] defaults = {80, 50, 80, 50, 80, 50, 80, 50};
|
||||||
|
|
||||||
|
group.addWidget(new ImageWidget(10, y, 80, 10,
|
||||||
|
new TextTexture(Component.translatable("gui.dglabgame.waveform.channel").getString(), 0xffcccccc)));
|
||||||
|
|
||||||
|
group.addWidget(new ButtonWidget(W / 2 + 40, y - 2, 40, 14, cd -> {})
|
||||||
|
.setBackground(new ColorRectTexture(0xff4444aa)));
|
||||||
|
|
||||||
|
y += 16;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
int fx = 10 + i * (W - 20) / 4;
|
||||||
|
TextFieldWidget ff = new TextFieldWidget(fx, y, 35, 12, () -> "", s -> {});
|
||||||
|
ff.setCurrentString(String.valueOf(defaults[i * 2]));
|
||||||
|
ff.setBordered(true);
|
||||||
|
ff.setId("wf_f" + (i + 1));
|
||||||
|
group.addWidget(ff);
|
||||||
|
|
||||||
|
TextFieldWidget sf = new TextFieldWidget(fx + 40, y, 35, 12, () -> "", s -> {});
|
||||||
|
sf.setCurrentString(String.valueOf(defaults[i * 2 + 1]));
|
||||||
|
sf.setBordered(true);
|
||||||
|
sf.setId("wf_s" + (i + 1));
|
||||||
|
group.addWidget(sf);
|
||||||
|
}
|
||||||
|
|
||||||
|
y += 18;
|
||||||
|
group.addWidget(new ButtonWidget(W / 2 - 30, y, 60, 16, cd -> {
|
||||||
|
try {
|
||||||
|
int f1 = parseIntField(group, "wf_f1"), f2 = parseIntField(group, "wf_f2");
|
||||||
|
int f3 = parseIntField(group, "wf_f3"), f4 = parseIntField(group, "wf_f4");
|
||||||
|
int s1 = parseIntField(group, "wf_s1"), s2 = parseIntField(group, "wf_s2");
|
||||||
|
int s3 = parseIntField(group, "wf_s3"), s4 = parseIntField(group, "wf_s4");
|
||||||
|
|
||||||
|
var waveList = PulseWaveListGenerator.pulseWave(
|
||||||
|
new int[]{f1, f2, f3, f4}, new int[]{s1, s2, s3, s4});
|
||||||
|
IPowerBoxMsg.Pulse msg = new IPowerBoxMsg.Pulse(Channel.A, waveList, 0);
|
||||||
|
PowerBoxMessage pbm = msg.toPowerBoxMessage(CLIENT_ID, CLIENT_ID,
|
||||||
|
MessageDirection.DirectType.CLIENT_TO_SERVER);
|
||||||
|
DGLabManagerHolder.getServerManager().ifPresent(mgr -> mgr.sendToAll(pbm));
|
||||||
|
} catch (NumberFormatException ignored) {}
|
||||||
|
}).setBackground(new ColorRectTexture(0xff994400)));
|
||||||
|
|
||||||
|
group.addWidget(new ButtonWidget(W / 2 + 38, y, 60, 16, cd -> {
|
||||||
|
try {
|
||||||
|
int f1 = parseIntField(group, "wf_f1"), f2 = parseIntField(group, "wf_f2");
|
||||||
|
int f3 = parseIntField(group, "wf_f3"), f4 = parseIntField(group, "wf_f4");
|
||||||
|
int s1 = parseIntField(group, "wf_s1"), s2 = parseIntField(group, "wf_s2");
|
||||||
|
int s3 = parseIntField(group, "wf_s3"), s4 = parseIntField(group, "wf_s4");
|
||||||
|
|
||||||
|
var waveList = PulseWaveListGenerator.pulseWave(
|
||||||
|
new int[]{f1, f2, f3, f4}, new int[]{s1, s2, s3, s4});
|
||||||
|
IPowerBoxMsg.Clear clear = new IPowerBoxMsg.Clear(Channel.A);
|
||||||
|
IPowerBoxMsg.Pulse pulse = new IPowerBoxMsg.Pulse(Channel.A, waveList, 0);
|
||||||
|
PowerBoxMessage clearMsg = clear.toPowerBoxMessage(CLIENT_ID, CLIENT_ID,
|
||||||
|
MessageDirection.DirectType.CLIENT_TO_SERVER);
|
||||||
|
PowerBoxMessage pulseMsg = pulse.toPowerBoxMessage(CLIENT_ID, CLIENT_ID,
|
||||||
|
MessageDirection.DirectType.CLIENT_TO_SERVER);
|
||||||
|
DGLabManagerHolder.getServerManager().ifPresent(mgr -> {
|
||||||
|
mgr.sendToAll(clearMsg);
|
||||||
|
mgr.sendToAll(pulseMsg);
|
||||||
|
});
|
||||||
|
} catch (NumberFormatException ignored) {}
|
||||||
|
}).setBackground(new ColorRectTexture(0xff994400)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int parseIntField(WidgetGroup group, String id) {
|
||||||
|
Widget w = group.getFirstWidgetById(id);
|
||||||
|
if (w instanceof TextFieldWidget tf) {
|
||||||
|
return Integer.parseInt(tf.getCurrentString());
|
||||||
|
}
|
||||||
|
throw new NumberFormatException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Feedback Tab ====================
|
||||||
|
|
||||||
|
private void buildFeedbackTab(WidgetGroup group) {
|
||||||
|
int y = 8;
|
||||||
|
group.addWidget(new ImageWidget(10, y, 80, 10,
|
||||||
|
new TextTexture(Component.translatable("gui.dglabgame.feedback.send").getString(), 0xffcccccc)));
|
||||||
|
|
||||||
|
y += 16;
|
||||||
|
var presets = ClientConfig.FEEDBACK_PRESETS.get();
|
||||||
|
int cols = 4;
|
||||||
|
int btnW = (W - 30) / cols;
|
||||||
|
int row = 0, col = 0;
|
||||||
|
for (String presetStr : presets) {
|
||||||
|
try {
|
||||||
|
int val = Integer.parseInt(presetStr.trim());
|
||||||
|
int bx = 10 + col * (btnW + 2);
|
||||||
|
int by = y + row * 18;
|
||||||
|
group.addWidget(new ButtonWidget(bx, by, btnW, 14, cd -> sendFeedback(val))
|
||||||
|
.setBackground(new ColorRectTexture(0xff444488)));
|
||||||
|
col++;
|
||||||
|
if (col >= cols) { col = 0; row++; }
|
||||||
|
} catch (NumberFormatException ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
y += (row + 1) * 18 + 6;
|
||||||
|
TextFieldWidget customField = new TextFieldWidget(10, y, 50, 14, () -> "", s -> {});
|
||||||
|
customField.setCurrentString("5");
|
||||||
|
customField.setBordered(true);
|
||||||
|
customField.setId("feedback_custom");
|
||||||
|
group.addWidget(customField);
|
||||||
|
|
||||||
|
group.addWidget(new ButtonWidget(65, y, 50, 14, cd -> {
|
||||||
|
try {
|
||||||
|
TextFieldWidget f = (TextFieldWidget) group.getFirstWidgetById("feedback_custom");
|
||||||
|
sendFeedback(Integer.parseInt(f.getCurrentString()));
|
||||||
|
} catch (NumberFormatException ignored) {}
|
||||||
|
}).setBackground(new ColorRectTexture(0xff444488)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendFeedback(int value) {
|
||||||
|
IPowerBoxMsg.Feedback msg = new IPowerBoxMsg.Feedback(Math.max(0, Math.min(10, value)));
|
||||||
|
PowerBoxMessage pbm = msg.toPowerBoxMessage(CLIENT_ID, CLIENT_ID,
|
||||||
|
MessageDirection.DirectType.CLIENT_TO_SERVER);
|
||||||
|
DGLabManagerHolder.getServerManager().ifPresent(mgr -> mgr.sendToAll(pbm));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Server Tab ====================
|
||||||
|
|
||||||
|
private void buildServerTab(WidgetGroup group) {
|
||||||
|
int y = 8;
|
||||||
|
group.addWidget(new ImageWidget(10, y, 60, 10,
|
||||||
|
new TextTexture(Component.translatable("gui.dglabgame.server.port").getString(), 0xffcccccc)));
|
||||||
|
TextFieldWidget portField = new TextFieldWidget(80, y, 60, 14, () -> "", s -> {});
|
||||||
|
portField.setCurrentString(String.valueOf(CommonConfig.SERVER_PORT.get()));
|
||||||
|
portField.setBordered(true);
|
||||||
|
portField.setId("server_port");
|
||||||
|
group.addWidget(portField);
|
||||||
|
|
||||||
|
y += 18;
|
||||||
|
group.addWidget(new ImageWidget(10, y, 60, 10,
|
||||||
|
new TextTexture(Component.translatable("gui.dglabgame.server.max_conn").getString(), 0xffcccccc)));
|
||||||
|
TextFieldWidget maxField = new TextFieldWidget(80, y, 60, 14, () -> "", s -> {});
|
||||||
|
maxField.setCurrentString(String.valueOf(CommonConfig.MAX_CONNECTIONS.get()));
|
||||||
|
maxField.setBordered(true);
|
||||||
|
maxField.setId("max_connections");
|
||||||
|
group.addWidget(maxField);
|
||||||
|
|
||||||
|
y += 20;
|
||||||
|
group.addWidget(new ButtonWidget(10, y, 60, 16, cd -> {
|
||||||
|
try {
|
||||||
|
TextFieldWidget pf = (TextFieldWidget) group.getFirstWidgetById("server_port");
|
||||||
|
TextFieldWidget mf = (TextFieldWidget) group.getFirstWidgetById("max_connections");
|
||||||
|
int port = Integer.parseInt(pf.getCurrentString());
|
||||||
|
int max = Integer.parseInt(mf.getCurrentString());
|
||||||
|
DLGNetworkHandler.CHANNEL.sendToServer(new UpdateServerConfigPacket(port, max));
|
||||||
|
} catch (NumberFormatException ignored) {}
|
||||||
|
}).setBackground(new ColorRectTexture(0xff336633)));
|
||||||
|
|
||||||
|
Optional<ServerManager> mgr = DGLabManagerHolder.getServerManager();
|
||||||
|
String statusText = mgr.map(m -> m.getStatus().name()).orElse("NO SERVER");
|
||||||
|
group.addWidget(new ImageWidget(80, y + 2, 120, 10,
|
||||||
|
new TextTexture(Component.translatable("gui.dglabgame.server.status", statusText).getString(), 0xffaaaaaa)));
|
||||||
|
|
||||||
|
y += 20;
|
||||||
|
group.addWidget(new ButtonWidget(10, y, 60, 16, cd -> {
|
||||||
|
Optional<ServerManager> sm = DGLabManagerHolder.getServerManager();
|
||||||
|
if (sm.isEmpty() || sm.get().getStatus() == Status.STOPPED) {
|
||||||
|
DGLabManagerHolder.getOrCreateServerManager().start();
|
||||||
|
}
|
||||||
|
}).setBackground(new ColorRectTexture(0xff226622)));
|
||||||
|
|
||||||
|
group.addWidget(new ButtonWidget(80, y, 60, 16, cd -> {
|
||||||
|
DGLabManagerHolder.getServerManager().ifPresent(ServerManager::stop);
|
||||||
|
}).setBackground(new ColorRectTexture(0xff662222)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Bottom Bar ====================
|
||||||
|
|
||||||
|
private WidgetGroup buildBottomBar() {
|
||||||
|
WidgetGroup bar = new WidgetGroup(5, H - 30, W - 10, 22);
|
||||||
|
bar.setBackground(ResourceBorderTexture.BORDERED_BACKGROUND);
|
||||||
|
|
||||||
|
bar.addWidget(new ImageWidget(10, 4, 40, 10,
|
||||||
|
new TextTexture(Component.translatable("gui.dglabgame.client.label").getString(), 0xffaaaaaa)));
|
||||||
|
|
||||||
|
var names = DGLabManagerHolder.getClientManager().getClientNames();
|
||||||
|
String current = names.isEmpty() ? "none" : names.iterator().next();
|
||||||
|
|
||||||
|
bar.addWidget(new ButtonWidget(55, 2, 60, 14, cd -> {
|
||||||
|
DGLabManagerHolder.getClientManager().getClient(current).ifPresent(DGPBClientManager::start);
|
||||||
|
}).setBackground(new ColorRectTexture(0xff226622)));
|
||||||
|
|
||||||
|
bar.addWidget(new ButtonWidget(120, 2, 60, 14, cd -> {
|
||||||
|
DGLabManagerHolder.getClientManager().getClient(current).ifPresent(DGPBClientManager::stop);
|
||||||
|
}).setBackground(new ColorRectTexture(0xff662222)));
|
||||||
|
|
||||||
|
return bar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package top.leisuretimedock.dglabgame.config;
|
||||||
|
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
import net.minecraftforge.common.ForgeConfigSpec;
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public class ClientConfig {
|
||||||
|
public static final ForgeConfigSpec SPEC;
|
||||||
|
|
||||||
|
public static final ForgeConfigSpec.BooleanValue ENABLE_SSL;
|
||||||
|
public static final ForgeConfigSpec.IntValue CONNECTION_TIMEOUT;
|
||||||
|
public static final ForgeConfigSpec.ConfigValue<java.util.List<? extends String>> FEEDBACK_PRESETS;
|
||||||
|
|
||||||
|
static {
|
||||||
|
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
|
||||||
|
|
||||||
|
builder.push("connection");
|
||||||
|
ENABLE_SSL = builder
|
||||||
|
.comment("Whether to use SSL/WSS for the WebSocket connection to the DGLab relay.",
|
||||||
|
"Requires a valid SSL certificate on the relay server side.")
|
||||||
|
.define("enableSSL", false);
|
||||||
|
CONNECTION_TIMEOUT = builder
|
||||||
|
.comment("Connection timeout in milliseconds for WebSocket handshake.")
|
||||||
|
.defineInRange("connectionTimeout", 5000, 1000, 30000);
|
||||||
|
builder.pop();
|
||||||
|
|
||||||
|
builder.push("feedback");
|
||||||
|
FEEDBACK_PRESETS = builder
|
||||||
|
.comment("Preset feedback message labels.",
|
||||||
|
"These appear as quick-select buttons in the management GUI.")
|
||||||
|
.defineList("presets",
|
||||||
|
java.util.List.of("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"),
|
||||||
|
o -> o instanceof String && !((String) o).isBlank());
|
||||||
|
builder.pop();
|
||||||
|
|
||||||
|
SPEC = builder.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
package top.leisuretimedock.dglabgame.config;
|
||||||
|
|
||||||
|
import net.minecraftforge.common.ForgeConfigSpec;
|
||||||
|
|
||||||
|
public class CommonConfig {
|
||||||
|
public static final ForgeConfigSpec SPEC;
|
||||||
|
|
||||||
|
public static final ForgeConfigSpec.ConfigValue<String> ADDRESS;
|
||||||
|
public static final ForgeConfigSpec.IntValue PORT;
|
||||||
|
|
||||||
|
public static final ForgeConfigSpec.IntValue MAX_STRENGTH_A;
|
||||||
|
public static final ForgeConfigSpec.IntValue MAX_STRENGTH_B;
|
||||||
|
public static final ForgeConfigSpec.IntValue MIN_STRENGTH_A;
|
||||||
|
public static final ForgeConfigSpec.IntValue MIN_STRENGTH_B;
|
||||||
|
|
||||||
|
public static final ForgeConfigSpec.IntValue MAX_FREQUENCY;
|
||||||
|
public static final ForgeConfigSpec.IntValue MIN_FREQUENCY;
|
||||||
|
public static final ForgeConfigSpec.IntValue MAX_PULSE_STRENGTH;
|
||||||
|
public static final ForgeConfigSpec.IntValue ANTI_SHAKE_DELAY;
|
||||||
|
|
||||||
|
public static final ForgeConfigSpec.IntValue COUNTDOWN_SECONDS;
|
||||||
|
|
||||||
|
public static final ForgeConfigSpec.IntValue SERVER_PORT;
|
||||||
|
public static final ForgeConfigSpec.IntValue MAX_CONNECTIONS;
|
||||||
|
|
||||||
|
static {
|
||||||
|
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
|
||||||
|
|
||||||
|
builder.push("websocket");
|
||||||
|
ADDRESS = builder
|
||||||
|
.comment("WebSocket server address for the DGLab PowerBox relay.",
|
||||||
|
"Change this if the relay is running on a different machine.")
|
||||||
|
.define("address", "127.0.0.1",
|
||||||
|
o -> o instanceof String && !((String) o).isBlank());
|
||||||
|
PORT = builder
|
||||||
|
.comment("WebSocket server port for the DGLab PowerBox relay.")
|
||||||
|
.defineInRange("port", 9000, 1, 65535);
|
||||||
|
builder.pop();
|
||||||
|
|
||||||
|
builder.push("strength_limits");
|
||||||
|
MAX_STRENGTH_A = builder
|
||||||
|
.comment("Maximum allowed strength for channel A.")
|
||||||
|
.defineInRange("maxStrengthA", 200, 0, 200);
|
||||||
|
MAX_STRENGTH_B = builder
|
||||||
|
.comment("Maximum allowed strength for channel B.")
|
||||||
|
.defineInRange("maxStrengthB", 200, 0, 200);
|
||||||
|
MIN_STRENGTH_A = builder
|
||||||
|
.comment("Minimum allowed strength for channel A.")
|
||||||
|
.defineInRange("minStrengthA", 0, 0, 200);
|
||||||
|
MIN_STRENGTH_B = builder
|
||||||
|
.comment("Minimum allowed strength for channel B.")
|
||||||
|
.defineInRange("minStrengthB", 0, 0, 200);
|
||||||
|
builder.pop();
|
||||||
|
|
||||||
|
builder.push("pulse");
|
||||||
|
MAX_FREQUENCY = builder
|
||||||
|
.comment("Maximum pulse frequency in Hz.")
|
||||||
|
.defineInRange("maxFrequency", 240, 10, 240);
|
||||||
|
MIN_FREQUENCY = builder
|
||||||
|
.comment("Minimum pulse frequency in Hz.")
|
||||||
|
.defineInRange("minFrequency", 10, 10, 240);
|
||||||
|
MAX_PULSE_STRENGTH = builder
|
||||||
|
.comment("Maximum pulse strength (0-100).")
|
||||||
|
.defineInRange("maxPulseStrength", 100, 0, 100);
|
||||||
|
ANTI_SHAKE_DELAY = builder
|
||||||
|
.comment("Anti-shake debounce delay in milliseconds.",
|
||||||
|
"Prevents rapid repeated pulse triggers within this window.")
|
||||||
|
.defineInRange("antiShakeDelay", 500, 0, 5000);
|
||||||
|
builder.pop();
|
||||||
|
|
||||||
|
builder.push("agreement");
|
||||||
|
COUNTDOWN_SECONDS = builder
|
||||||
|
.comment("Countdown duration in seconds for the user agreement confirmation screen.",
|
||||||
|
"Set to 0 to allow instant confirmation (not recommended).")
|
||||||
|
.defineInRange("countdownSeconds", 5, 0, 60);
|
||||||
|
builder.pop();
|
||||||
|
|
||||||
|
builder.push("server");
|
||||||
|
SERVER_PORT = builder
|
||||||
|
.comment("Port for the DGLab WebSocket server to listen on.",
|
||||||
|
"Restart the server for changes to take effect.")
|
||||||
|
.defineInRange("serverPort", 9000, 1, 65535);
|
||||||
|
MAX_CONNECTIONS = builder
|
||||||
|
.comment("Maximum number of concurrent WebSocket connections allowed.",
|
||||||
|
"Additional connections beyond this limit will be rejected.")
|
||||||
|
.defineInRange("maxConnections", 128, 1, 1024);
|
||||||
|
builder.pop();
|
||||||
|
|
||||||
|
SPEC = builder.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
package top.leisuretimedock.dglabgame.core.capability;
|
package top.leisuretimedock.dglabgame.core.capability;
|
||||||
|
|
||||||
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
import top.r3944realms.lib39.core.sync.CachedSyncManager;
|
import top.r3944realms.lib39.core.sync.CachedSyncManager;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class DGLabDataSyncManager extends CachedSyncManager<UUID, AbstractDGLabData> {
|
public class DGLabDataSyncManager extends CachedSyncManager<Capability<AbstractDGLabData>, AbstractDGLabData> {
|
||||||
public static Map<UUID, AbstractDGLabData> playerDungeonData = new HashMap<>();
|
public static Map<Capability<AbstractDGLabData>, AbstractDGLabData> playerDungeonData = new HashMap<>();
|
||||||
@Override
|
@Override
|
||||||
public Map<UUID, AbstractDGLabData> getSyncMap() {
|
public Map<Capability<AbstractDGLabData>, AbstractDGLabData> getSyncMap() {
|
||||||
return playerDungeonData;
|
return playerDungeonData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,4 +34,8 @@ public final class EntityDGLabData extends AbstractDGLabData {
|
||||||
public int entityId() {
|
public int entityId() {
|
||||||
return entity.getId();
|
return entity.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,410 @@
|
||||||
|
package top.leisuretimedock.dglabgame.core.command;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
import com.r3944realms.dg_lab.api.manager.Status;
|
||||||
|
import com.r3944realms.dg_lab.api.message.IPowerBoxMsg;
|
||||||
|
import com.r3944realms.dg_lab.api.message.argType.Channel;
|
||||||
|
import com.r3944realms.dg_lab.api.message.argType.ChangePolicy;
|
||||||
|
import com.r3944realms.dg_lab.api.message.data.PulseWaveListGenerator;
|
||||||
|
import com.r3944realms.dg_lab.api.websocket.message.MessageDirection;
|
||||||
|
import com.r3944realms.dg_lab.api.websocket.message.PowerBoxMessage;
|
||||||
|
import com.r3944realms.dg_lab.api.websocket.message.role.WebSocketClientRole;
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
import net.minecraft.commands.Commands;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import top.leisuretimedock.dglabgame.config.CommonConfig;
|
||||||
|
import top.leisuretimedock.dglabgame.core.manager.ClientManager;
|
||||||
|
import top.leisuretimedock.dglabgame.core.manager.DGLabManagerHolder;
|
||||||
|
import top.leisuretimedock.dglabgame.core.manager.ServerManager;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class DGLabCommands {
|
||||||
|
private static final String CLIENT_ID = "dglabgame";
|
||||||
|
|
||||||
|
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||||
|
dispatcher.register(
|
||||||
|
Commands.literal("dglab")
|
||||||
|
.requires(source -> source.hasPermission(2))
|
||||||
|
.then(serverNode())
|
||||||
|
.then(clientNode())
|
||||||
|
.then(strengthNode())
|
||||||
|
.then(pulseNode())
|
||||||
|
.then(clearNode())
|
||||||
|
.then(feedbackNode())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Server Commands ====================
|
||||||
|
|
||||||
|
private static com.mojang.brigadier.builder.LiteralArgumentBuilder<CommandSourceStack> serverNode() {
|
||||||
|
return Commands.literal("server")
|
||||||
|
.then(Commands.literal("start")
|
||||||
|
.executes(ctx -> serverStart(ctx, CommonConfig.PORT.get()))
|
||||||
|
.then(Commands.argument("port", IntegerArgumentType.integer(1, 65535))
|
||||||
|
.executes(ctx -> serverStart(ctx, IntegerArgumentType.getInteger(ctx, "port")))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("stop")
|
||||||
|
.executes(DGLabCommands::serverStop)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("status")
|
||||||
|
.executes(DGLabCommands::serverStatus)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int serverStart(CommandContext<CommandSourceStack> ctx, int port) {
|
||||||
|
Optional<ServerManager> existing = DGLabManagerHolder.getServerManager();
|
||||||
|
if (existing.isPresent() && existing.get().getStatus() != Status.STOPPED) {
|
||||||
|
ctx.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("dglabgame.command.server.already_running"), false
|
||||||
|
);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ServerManager mgr = DGLabManagerHolder.getOrCreateServerManager();
|
||||||
|
mgr.start();
|
||||||
|
ctx.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("dglabgame.command.server.started", port), true
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int serverStop(CommandContext<CommandSourceStack> ctx) {
|
||||||
|
Optional<ServerManager> existing = DGLabManagerHolder.getServerManager();
|
||||||
|
if (existing.isEmpty() || existing.get().getStatus() == Status.STOPPED) {
|
||||||
|
ctx.getSource().sendFailure(
|
||||||
|
Component.translatable("dglabgame.command.server.not_running")
|
||||||
|
);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
existing.get().stop();
|
||||||
|
ctx.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("dglabgame.command.server.stopped"), true
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int serverStatus(CommandContext<CommandSourceStack> ctx) {
|
||||||
|
Optional<ServerManager> existing = DGLabManagerHolder.getServerManager();
|
||||||
|
if (existing.isEmpty()) {
|
||||||
|
ctx.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("dglabgame.command.server.not_created"), false
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ServerManager mgr = existing.get();
|
||||||
|
Status status = mgr.getStatus();
|
||||||
|
int clients = mgr.getConnectedClients().size();
|
||||||
|
ctx.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("dglabgame.command.server.status", status.name(), clients), false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Client Commands ====================
|
||||||
|
|
||||||
|
private static com.mojang.brigadier.builder.LiteralArgumentBuilder<CommandSourceStack> clientNode() {
|
||||||
|
return Commands.literal("client")
|
||||||
|
.then(Commands.literal("create")
|
||||||
|
.then(Commands.argument("name", StringArgumentType.word())
|
||||||
|
.executes(ctx -> clientCreate(ctx,
|
||||||
|
StringArgumentType.getString(ctx, "name"),
|
||||||
|
CommonConfig.ADDRESS.get(),
|
||||||
|
CommonConfig.PORT.get()))
|
||||||
|
.then(Commands.argument("address", StringArgumentType.word())
|
||||||
|
.executes(ctx -> clientCreate(ctx,
|
||||||
|
StringArgumentType.getString(ctx, "name"),
|
||||||
|
StringArgumentType.getString(ctx, "address"),
|
||||||
|
CommonConfig.PORT.get()))
|
||||||
|
.then(Commands.argument("port", IntegerArgumentType.integer(1, 65535))
|
||||||
|
.executes(ctx -> clientCreate(ctx,
|
||||||
|
StringArgumentType.getString(ctx, "name"),
|
||||||
|
StringArgumentType.getString(ctx, "address"),
|
||||||
|
IntegerArgumentType.getInteger(ctx, "port")))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("remove")
|
||||||
|
.then(Commands.argument("name", StringArgumentType.word())
|
||||||
|
.executes(DGLabCommands::clientRemove)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("start")
|
||||||
|
.then(Commands.argument("name", StringArgumentType.word())
|
||||||
|
.executes(DGLabCommands::clientStart)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("stop")
|
||||||
|
.then(Commands.argument("name", StringArgumentType.word())
|
||||||
|
.executes(DGLabCommands::clientStop)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(Commands.literal("list")
|
||||||
|
.executes(DGLabCommands::clientList)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int clientCreate(CommandContext<CommandSourceStack> ctx, String name, String address, int port) {
|
||||||
|
ClientManager mgr = DGLabManagerHolder.getClientManager();
|
||||||
|
WebSocketClientRole role = WebSocketClientRole.of(CLIENT_ID + "_" + name);
|
||||||
|
mgr.createClient(name, role, address, port);
|
||||||
|
ctx.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("dglabgame.command.client.created", name, address, port), true
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int clientRemove(CommandContext<CommandSourceStack> ctx) {
|
||||||
|
String name = StringArgumentType.getString(ctx, "name");
|
||||||
|
ClientManager mgr = DGLabManagerHolder.getClientManager();
|
||||||
|
if (mgr.getClient(name).isEmpty()) {
|
||||||
|
ctx.getSource().sendFailure(
|
||||||
|
Component.translatable("dglabgame.command.client.not_found", name)
|
||||||
|
);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
mgr.removeClient(name);
|
||||||
|
ctx.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("dglabgame.command.client.removed", name), true
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int clientStart(CommandContext<CommandSourceStack> ctx) {
|
||||||
|
String name = StringArgumentType.getString(ctx, "name");
|
||||||
|
ClientManager mgr = DGLabManagerHolder.getClientManager();
|
||||||
|
Optional<com.r3944realms.dg_lab.manager.DGPBClientManager> client = mgr.getClient(name);
|
||||||
|
if (client.isEmpty()) {
|
||||||
|
ctx.getSource().sendFailure(
|
||||||
|
Component.translatable("dglabgame.command.client.not_found", name)
|
||||||
|
);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
client.get().start();
|
||||||
|
ctx.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("dglabgame.command.client.started", name), true
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int clientStop(CommandContext<CommandSourceStack> ctx) {
|
||||||
|
String name = StringArgumentType.getString(ctx, "name");
|
||||||
|
ClientManager mgr = DGLabManagerHolder.getClientManager();
|
||||||
|
Optional<com.r3944realms.dg_lab.manager.DGPBClientManager> client = mgr.getClient(name);
|
||||||
|
if (client.isEmpty()) {
|
||||||
|
ctx.getSource().sendFailure(
|
||||||
|
Component.translatable("dglabgame.command.client.not_found", name)
|
||||||
|
);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
client.get().stop();
|
||||||
|
ctx.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("dglabgame.command.client.stopped", name), true
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int clientList(CommandContext<CommandSourceStack> ctx) {
|
||||||
|
ClientManager mgr = DGLabManagerHolder.getClientManager();
|
||||||
|
var names = mgr.getClientNames();
|
||||||
|
if (names.isEmpty()) {
|
||||||
|
ctx.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("dglabgame.command.client.none"), false
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
String list = String.join(", ", names);
|
||||||
|
ctx.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("dglabgame.command.client.list", list), false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Device Commands ====================
|
||||||
|
|
||||||
|
private static com.mojang.brigadier.builder.LiteralArgumentBuilder<CommandSourceStack> strengthNode() {
|
||||||
|
return Commands.literal("strength")
|
||||||
|
.then(Commands.argument("channel", StringArgumentType.word())
|
||||||
|
.then(Commands.argument("policy", StringArgumentType.word())
|
||||||
|
.then(Commands.argument("value", IntegerArgumentType.integer(0, 200))
|
||||||
|
.executes(DGLabCommands::strengthExec)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int strengthExec(CommandContext<CommandSourceStack> ctx) {
|
||||||
|
Channel channel = parseChannel(StringArgumentType.getString(ctx, "channel"));
|
||||||
|
if (channel == null) {
|
||||||
|
ctx.getSource().sendFailure(Component.translatable("dglabgame.command.invalid_channel"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ChangePolicy policy = parsePolicy(StringArgumentType.getString(ctx, "policy"));
|
||||||
|
if (policy == null) {
|
||||||
|
ctx.getSource().sendFailure(Component.translatable("dglabgame.command.invalid_policy"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int value = IntegerArgumentType.getInteger(ctx, "value");
|
||||||
|
|
||||||
|
IPowerBoxMsg.StrengthChange msg = new IPowerBoxMsg.StrengthChange(channel, policy, value);
|
||||||
|
int sent = sendToAll(msg);
|
||||||
|
if (sent == 0) {
|
||||||
|
ctx.getSource().sendFailure(Component.translatable("dglabgame.command.no_output"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ctx.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("dglabgame.command.strength.sent", channel.name(), policy.name(), value, sent), true
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static com.mojang.brigadier.builder.LiteralArgumentBuilder<CommandSourceStack> pulseNode() {
|
||||||
|
return Commands.literal("pulse")
|
||||||
|
.then(Commands.argument("channel", StringArgumentType.word())
|
||||||
|
.then(Commands.argument("f1", IntegerArgumentType.integer(10, 240))
|
||||||
|
.then(Commands.argument("s1", IntegerArgumentType.integer(0, 100))
|
||||||
|
.then(Commands.argument("f2", IntegerArgumentType.integer(10, 240))
|
||||||
|
.then(Commands.argument("s2", IntegerArgumentType.integer(0, 100))
|
||||||
|
.then(Commands.argument("f3", IntegerArgumentType.integer(10, 240))
|
||||||
|
.then(Commands.argument("s3", IntegerArgumentType.integer(0, 100))
|
||||||
|
.then(Commands.argument("f4", IntegerArgumentType.integer(10, 240))
|
||||||
|
.then(Commands.argument("s4", IntegerArgumentType.integer(0, 100))
|
||||||
|
.executes(DGLabCommands::pulseExec)
|
||||||
|
.then(Commands.argument("timer", IntegerArgumentType.integer(0, 60000))
|
||||||
|
.executes(DGLabCommands::pulseExec)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int pulseExec(CommandContext<CommandSourceStack> ctx) {
|
||||||
|
Channel channel = parseChannel(StringArgumentType.getString(ctx, "channel"));
|
||||||
|
if (channel == null) {
|
||||||
|
ctx.getSource().sendFailure(Component.translatable("dglabgame.command.invalid_channel"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int f1 = IntegerArgumentType.getInteger(ctx, "f1");
|
||||||
|
int s1 = IntegerArgumentType.getInteger(ctx, "s1");
|
||||||
|
int f2 = IntegerArgumentType.getInteger(ctx, "f2");
|
||||||
|
int s2 = IntegerArgumentType.getInteger(ctx, "s2");
|
||||||
|
int f3 = IntegerArgumentType.getInteger(ctx, "f3");
|
||||||
|
int s3 = IntegerArgumentType.getInteger(ctx, "s3");
|
||||||
|
int f4 = IntegerArgumentType.getInteger(ctx, "f4");
|
||||||
|
int s4 = IntegerArgumentType.getInteger(ctx, "s4");
|
||||||
|
|
||||||
|
var waveList = PulseWaveListGenerator.pulseWave(
|
||||||
|
new int[]{f1, f2, f3, f4},
|
||||||
|
new int[]{s1, s2, s3, s4}
|
||||||
|
);
|
||||||
|
|
||||||
|
Integer timer = null;
|
||||||
|
try {
|
||||||
|
timer = IntegerArgumentType.getInteger(ctx, "timer");
|
||||||
|
} catch (IllegalArgumentException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
IPowerBoxMsg.Pulse msg = new IPowerBoxMsg.Pulse(channel, waveList, timer);
|
||||||
|
int sent = sendToAll(msg);
|
||||||
|
if (sent == 0) {
|
||||||
|
ctx.getSource().sendFailure(Component.translatable("dglabgame.command.no_output"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ctx.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("dglabgame.command.pulse.sent", channel.name(), sent), true
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static com.mojang.brigadier.builder.LiteralArgumentBuilder<CommandSourceStack> clearNode() {
|
||||||
|
return Commands.literal("clear")
|
||||||
|
.then(Commands.argument("channel", StringArgumentType.word())
|
||||||
|
.executes(DGLabCommands::clearExec)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int clearExec(CommandContext<CommandSourceStack> ctx) {
|
||||||
|
Channel channel = parseChannel(StringArgumentType.getString(ctx, "channel"));
|
||||||
|
if (channel == null) {
|
||||||
|
ctx.getSource().sendFailure(Component.translatable("dglabgame.command.invalid_channel"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPowerBoxMsg.Clear msg = new IPowerBoxMsg.Clear(channel);
|
||||||
|
int sent = sendToAll(msg);
|
||||||
|
if (sent == 0) {
|
||||||
|
ctx.getSource().sendFailure(Component.translatable("dglabgame.command.no_output"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ctx.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("dglabgame.command.clear.sent", channel.name(), sent), true
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static com.mojang.brigadier.builder.LiteralArgumentBuilder<CommandSourceStack> feedbackNode() {
|
||||||
|
return Commands.literal("feedback")
|
||||||
|
.then(Commands.argument("value", IntegerArgumentType.integer(0, 10))
|
||||||
|
.executes(DGLabCommands::feedbackExec)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int feedbackExec(CommandContext<CommandSourceStack> ctx) {
|
||||||
|
int value = IntegerArgumentType.getInteger(ctx, "value");
|
||||||
|
|
||||||
|
IPowerBoxMsg.Feedback msg = new IPowerBoxMsg.Feedback(value);
|
||||||
|
int sent = sendToAll(msg);
|
||||||
|
if (sent == 0) {
|
||||||
|
ctx.getSource().sendFailure(Component.translatable("dglabgame.command.no_output"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ctx.getSource().sendSuccess(
|
||||||
|
() -> Component.translatable("dglabgame.command.feedback.sent", value, sent), true
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Send Helpers ====================
|
||||||
|
|
||||||
|
private static int sendToAll(IPowerBoxMsg msg) {
|
||||||
|
int sent = 0;
|
||||||
|
Optional<ServerManager> serverMgr = DGLabManagerHolder.getServerManager();
|
||||||
|
if (serverMgr.isPresent()) {
|
||||||
|
ServerManager mgr = serverMgr.get();
|
||||||
|
if (mgr.getStatus() == Status.RUNNING) {
|
||||||
|
PowerBoxMessage pbm = msg.toPowerBoxMessage(CLIENT_ID, CLIENT_ID,
|
||||||
|
MessageDirection.DirectType.SERVER_TO_CLIENT);
|
||||||
|
mgr.sendToAll(pbm);
|
||||||
|
sent += mgr.getConnectedClients().size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Channel parseChannel(String s) {
|
||||||
|
return switch (s.toLowerCase()) {
|
||||||
|
case "a" -> Channel.A;
|
||||||
|
case "b" -> Channel.B;
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ChangePolicy parsePolicy(String s) {
|
||||||
|
return switch (s.toLowerCase()) {
|
||||||
|
case "increase", "inc", "+" -> ChangePolicy.INCREASE;
|
||||||
|
case "decrease", "dec", "-" -> ChangePolicy.DECREASE;
|
||||||
|
case "goto", "set", "=" -> ChangePolicy.GOTO;
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,6 +16,7 @@ import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||||
import top.leisuretimedock.dglabgame.DGLabGame;
|
import top.leisuretimedock.dglabgame.DGLabGame;
|
||||||
import top.leisuretimedock.dglabgame.client.DLGKeyMapping;
|
import top.leisuretimedock.dglabgame.client.DLGKeyMapping;
|
||||||
import top.leisuretimedock.dglabgame.client.gui.ConfirmGui;
|
import top.leisuretimedock.dglabgame.client.gui.ConfirmGui;
|
||||||
|
import top.leisuretimedock.dglabgame.client.gui.DGLabManagementGui;
|
||||||
import top.leisuretimedock.dglabgame.core.capability.DGLabDataProvider;
|
import top.leisuretimedock.dglabgame.core.capability.DGLabDataProvider;
|
||||||
|
|
||||||
public class ClientEventHandler {
|
public class ClientEventHandler {
|
||||||
|
|
@ -33,6 +34,15 @@ public class ClientEventHandler {
|
||||||
} else player.displayClientMessage(Component.literal("You had accept use agreements").withStyle(ChatFormatting.RED).withStyle(ChatFormatting.BOLD), true);
|
} else player.displayClientMessage(Component.literal("You had accept use agreements").withStyle(ChatFormatting.RED).withStyle(ChatFormatting.BOLD), true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (DLGKeyMapping.KEY_MANAGEMENT.isDown()) {
|
||||||
|
player.getCapability(DGLabDataProvider.DG_LAB_DATA_CAPABILITY).ifPresent(data -> {
|
||||||
|
if (data.hasAcceptUseAgreements()) {
|
||||||
|
new DGLabManagementGui().display();
|
||||||
|
} else {
|
||||||
|
player.displayClientMessage(Component.translatable("dglabgame.user_agreement.reject_use").withStyle(ChatFormatting.RED), true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@net.minecraftforge.fml.common.Mod.EventBusSubscriber(modid = DGLabGame.MOD_ID, bus = net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
|
@net.minecraftforge.fml.common.Mod.EventBusSubscriber(modid = DGLabGame.MOD_ID, bus = net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
|
||||||
|
|
@ -40,6 +50,7 @@ public class ClientEventHandler {
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onRegisterKeyMappings (RegisterKeyMappingsEvent event) {
|
public static void onRegisterKeyMappings (RegisterKeyMappingsEvent event) {
|
||||||
event.register(DLGKeyMapping.KEY_TEST);
|
event.register(DLGKeyMapping.KEY_TEST);
|
||||||
|
event.register(DLGKeyMapping.KEY_MANAGEMENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,12 @@ import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
|
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
|
||||||
import net.minecraftforge.data.event.GatherDataEvent;
|
import net.minecraftforge.data.event.GatherDataEvent;
|
||||||
import net.minecraftforge.event.AttachCapabilitiesEvent;
|
import net.minecraftforge.event.AttachCapabilitiesEvent;
|
||||||
|
import net.minecraftforge.event.RegisterCommandsEvent;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import top.leisuretimedock.dglabgame.DGLabGame;
|
import top.leisuretimedock.dglabgame.DGLabGame;
|
||||||
import top.leisuretimedock.dglabgame.core.capability.DGLabDataProvider;
|
import top.leisuretimedock.dglabgame.core.capability.DGLabDataProvider;
|
||||||
import top.leisuretimedock.dglabgame.core.capability.DGLabDataSyncManager;
|
import top.leisuretimedock.dglabgame.core.capability.DGLabDataSyncManager;
|
||||||
|
import top.leisuretimedock.dglabgame.core.command.DGLabCommands;
|
||||||
import top.leisuretimedock.dglabgame.core.register.DLGCapabilities;
|
import top.leisuretimedock.dglabgame.core.register.DLGCapabilities;
|
||||||
import top.leisuretimedock.dglabgame.datagen.DLGDataGenEvent;
|
import top.leisuretimedock.dglabgame.datagen.DLGDataGenEvent;
|
||||||
import top.r3944realms.lib39.api.event.SyncManagerRegisterEvent;
|
import top.r3944realms.lib39.api.event.SyncManagerRegisterEvent;
|
||||||
|
|
@ -41,5 +43,10 @@ public class CommonEventHandler {
|
||||||
public static void attachCapability(AttachCapabilitiesEvent<?> event) {
|
public static void attachCapability(AttachCapabilitiesEvent<?> event) {
|
||||||
DLGCapabilities.attachCapability(event);
|
DLGCapabilities.attachCapability(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onRegisterCommands(RegisterCommandsEvent event) {
|
||||||
|
DGLabCommands.register(event.getDispatcher());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
package top.leisuretimedock.dglabgame.core.manager;
|
||||||
|
|
||||||
|
import com.r3944realms.dg_lab.api.websocket.message.role.WebSocketClientRole;
|
||||||
|
import com.r3944realms.dg_lab.manager.DGPBClientManager;
|
||||||
|
import com.r3944realms.dg_lab.websocket.PowerBoxWSClient;
|
||||||
|
import com.r3944realms.dg_lab.websocket.handler.client.DefaultClientOperation;
|
||||||
|
import com.r3944realms.dg_lab.websocket.sharedData.ClientPowerBoxSharedData;
|
||||||
|
import top.leisuretimedock.dglabgame.config.CommonConfig;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class ClientManager implements IManager<Map<String, DGPBClientManager>> {
|
||||||
|
private final Map<String, DGPBClientManager> clients = new HashMap<>();
|
||||||
|
|
||||||
|
public DGPBClientManager createClient(String key, WebSocketClientRole role) {
|
||||||
|
return createClient(key, role, CommonConfig.ADDRESS.get(), CommonConfig.PORT.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public DGPBClientManager createClient(String key, WebSocketClientRole role, String address, int port) {
|
||||||
|
ClientPowerBoxSharedData sharedData = new ClientPowerBoxSharedData(
|
||||||
|
CommonConfig.ANTI_SHAKE_DELAY.get()
|
||||||
|
);
|
||||||
|
sharedData.address = address;
|
||||||
|
sharedData.port = port;
|
||||||
|
|
||||||
|
PowerBoxWSClient wsClient = new PowerBoxWSClient(
|
||||||
|
sharedData, role, new DefaultClientOperation(),
|
||||||
|
address, port
|
||||||
|
);
|
||||||
|
DGPBClientManager client = new DGPBClientManager(wsClient);
|
||||||
|
clients.putIfAbsent(key, client);
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public java.util.Set<String> getClientNames() {
|
||||||
|
return clients.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addClient(String key, DGPBClientManager client) {
|
||||||
|
clients.putIfAbsent(key, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeClient(String key) {
|
||||||
|
Optional.ofNullable(clients.remove(key)).ifPresent(DGPBClientManager::stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<DGPBClientManager> getClient(String key) {
|
||||||
|
return Optional.ofNullable(clients.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startAll() {
|
||||||
|
clients.values().forEach(DGPBClientManager::start);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopAll() {
|
||||||
|
clients.values().forEach(DGPBClientManager::stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<Map<String, DGPBClientManager>> getInstance() {
|
||||||
|
return Optional.of(clients);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package top.leisuretimedock.dglabgame.core.manager;
|
||||||
|
|
||||||
|
import com.r3944realms.dg_lab.api.websocket.message.role.WebSocketServerRole;
|
||||||
|
import com.r3944realms.dg_lab.manager.DGPBServerManager;
|
||||||
|
import com.r3944realms.dg_lab.websocket.PowerBoxWSServer;
|
||||||
|
import com.r3944realms.dg_lab.websocket.handler.server.DefaultServerOperation;
|
||||||
|
import com.r3944realms.dg_lab.websocket.sharedData.ServerPowerBoxSharedData;
|
||||||
|
import top.leisuretimedock.dglabgame.config.CommonConfig;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class DGLabManagerHolder {
|
||||||
|
private static ServerManager serverManager;
|
||||||
|
private static final ClientManager clientManager = new ClientManager();
|
||||||
|
|
||||||
|
public static ClientManager getClientManager() {
|
||||||
|
return clientManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<ServerManager> getServerManager() {
|
||||||
|
return Optional.ofNullable(serverManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerManager getOrCreateServerManager() {
|
||||||
|
if (serverManager == null) {
|
||||||
|
ServerPowerBoxSharedData sharedData = new ServerPowerBoxSharedData();
|
||||||
|
WebSocketServerRole role = WebSocketServerRole.of("dglabgame-server");
|
||||||
|
PowerBoxWSServer server = new PowerBoxWSServer(
|
||||||
|
sharedData, role, new DefaultServerOperation(),
|
||||||
|
CommonConfig.SERVER_PORT.get()
|
||||||
|
);
|
||||||
|
DGPBServerManager dgpbServerManager = new DGPBServerManager(server);
|
||||||
|
serverManager = new ServerManager(dgpbServerManager);
|
||||||
|
}
|
||||||
|
return serverManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setServerManager(ServerManager manager) {
|
||||||
|
if (serverManager != null) {
|
||||||
|
serverManager.stopAll();
|
||||||
|
}
|
||||||
|
serverManager = manager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package top.leisuretimedock.dglabgame.core.manager;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface IManager<T> {
|
||||||
|
void startAll();
|
||||||
|
void stopAll();
|
||||||
|
Optional<T> getInstance();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
package top.leisuretimedock.dglabgame.core.manager;
|
||||||
|
|
||||||
|
import com.r3944realms.dg_lab.api.manager.Status;
|
||||||
|
import com.r3944realms.dg_lab.api.websocket.message.Message;
|
||||||
|
import com.r3944realms.dg_lab.api.websocket.sharedData.ISharedData;
|
||||||
|
import com.r3944realms.dg_lab.manager.DGPBServerManager;
|
||||||
|
import com.r3944realms.dg_lab.manager.IDGLabManager;
|
||||||
|
import com.r3944realms.dg_lab.websocket.sharedData.ServerPowerBoxSharedData;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class ServerManager implements IManager<DGPBServerManager>, IDGLabManager {
|
||||||
|
private final DGPBServerManager serverManager;
|
||||||
|
|
||||||
|
public ServerManager(@NotNull DGPBServerManager serverManager) {
|
||||||
|
this.serverManager = serverManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
serverManager.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
serverManager.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ISharedData getSharedData() {
|
||||||
|
return serverManager.getSharedData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Status getStatus() {
|
||||||
|
return serverManager.getStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setStatus(Status status) {
|
||||||
|
serverManager.setStatus(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startAll() {
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopAll() {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<DGPBServerManager> getInstance() {
|
||||||
|
return Optional.of(serverManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendToAll(Message message) {
|
||||||
|
ISharedData sd = serverManager.getSharedData();
|
||||||
|
if (sd instanceof ServerPowerBoxSharedData spsd) {
|
||||||
|
spsd.connections.keySet().forEach(id -> serverManager.send(id, message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getConnectedClients() {
|
||||||
|
ISharedData sd = serverManager.getSharedData();
|
||||||
|
if (sd instanceof ServerPowerBoxSharedData spsd) {
|
||||||
|
return spsd.connections.keySet();
|
||||||
|
}
|
||||||
|
return Set.of();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,8 @@ import net.minecraftforge.network.NetworkRegistry;
|
||||||
import net.minecraftforge.network.simple.SimpleChannel;
|
import net.minecraftforge.network.simple.SimpleChannel;
|
||||||
import top.leisuretimedock.dglabgame.DGLabGame;
|
import top.leisuretimedock.dglabgame.DGLabGame;
|
||||||
import top.leisuretimedock.dglabgame.core.network.toServer.AcceptUserAgreementPacket;
|
import top.leisuretimedock.dglabgame.core.network.toServer.AcceptUserAgreementPacket;
|
||||||
|
import top.leisuretimedock.dglabgame.core.network.toServer.UpdateServerConfigPacket;
|
||||||
|
import top.leisuretimedock.dglabgame.core.network.toServer.UpdateStrengthConfigPacket;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
|
@ -22,6 +24,16 @@ public class DLGNetworkHandler {
|
||||||
.decoder(AcceptUserAgreementPacket::decode)
|
.decoder(AcceptUserAgreementPacket::decode)
|
||||||
.consumerMainThread(AcceptUserAgreementPacket::handle)
|
.consumerMainThread(AcceptUserAgreementPacket::handle)
|
||||||
.add();
|
.add();
|
||||||
|
CHANNEL.messageBuilder(UpdateServerConfigPacket.class, getIndex(), NetworkDirection.PLAY_TO_SERVER)
|
||||||
|
.encoder(UpdateServerConfigPacket::encode)
|
||||||
|
.decoder(UpdateServerConfigPacket::decode)
|
||||||
|
.consumerMainThread(UpdateServerConfigPacket::handle)
|
||||||
|
.add();
|
||||||
|
CHANNEL.messageBuilder(UpdateStrengthConfigPacket.class, getIndex(), NetworkDirection.PLAY_TO_SERVER)
|
||||||
|
.encoder(UpdateStrengthConfigPacket::encode)
|
||||||
|
.decoder(UpdateStrengthConfigPacket::decode)
|
||||||
|
.consumerMainThread(UpdateStrengthConfigPacket::handle)
|
||||||
|
.add();
|
||||||
|
|
||||||
}
|
}
|
||||||
public static int getIndex() {
|
public static int getIndex() {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
package top.leisuretimedock.dglabgame.core.network.toServer;
|
||||||
|
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraftforge.network.NetworkEvent;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import top.leisuretimedock.dglabgame.config.CommonConfig;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public record UpdateServerConfigPacket(int serverPort, int maxConnections) {
|
||||||
|
public void encode(FriendlyByteBuf buf) {
|
||||||
|
buf.writeVarInt(serverPort);
|
||||||
|
buf.writeVarInt(maxConnections);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UpdateServerConfigPacket decode(FriendlyByteBuf buf) {
|
||||||
|
return new UpdateServerConfigPacket(buf.readVarInt(), buf.readVarInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handle(@NotNull Supplier<NetworkEvent.Context> contextSupplier) {
|
||||||
|
NetworkEvent.Context context = contextSupplier.get();
|
||||||
|
context.enqueueWork(() -> {
|
||||||
|
ServerPlayer sender = context.getSender();
|
||||||
|
if (sender != null && sender.hasPermissions(4)) {
|
||||||
|
CommonConfig.SERVER_PORT.set(serverPort);
|
||||||
|
CommonConfig.MAX_CONNECTIONS.set(maxConnections);
|
||||||
|
CommonConfig.SPEC.save();
|
||||||
|
}
|
||||||
|
context.setPacketHandled(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package top.leisuretimedock.dglabgame.core.network.toServer;
|
||||||
|
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraftforge.network.NetworkEvent;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import top.leisuretimedock.dglabgame.config.CommonConfig;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public record UpdateStrengthConfigPacket(int maxA, int minA, int maxB, int minB) {
|
||||||
|
public void encode(FriendlyByteBuf buf) {
|
||||||
|
buf.writeVarInt(maxA);
|
||||||
|
buf.writeVarInt(minA);
|
||||||
|
buf.writeVarInt(maxB);
|
||||||
|
buf.writeVarInt(minB);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UpdateStrengthConfigPacket decode(FriendlyByteBuf buf) {
|
||||||
|
return new UpdateStrengthConfigPacket(buf.readVarInt(), buf.readVarInt(), buf.readVarInt(), buf.readVarInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handle(@NotNull Supplier<NetworkEvent.Context> contextSupplier) {
|
||||||
|
NetworkEvent.Context context = contextSupplier.get();
|
||||||
|
context.enqueueWork(() -> {
|
||||||
|
ServerPlayer sender = context.getSender();
|
||||||
|
if (sender != null) {
|
||||||
|
CommonConfig.MAX_STRENGTH_A.set(maxA);
|
||||||
|
CommonConfig.MIN_STRENGTH_A.set(minA);
|
||||||
|
CommonConfig.MAX_STRENGTH_B.set(maxB);
|
||||||
|
CommonConfig.MIN_STRENGTH_B.set(minB);
|
||||||
|
CommonConfig.SPEC.save();
|
||||||
|
}
|
||||||
|
context.setPacketHandled(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -61,6 +61,15 @@ public enum DLGLangKey implements ILangKeyValueCollection {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
addLang(
|
||||||
|
LangKeyValue.ofKey("dglabgame.user_agreement.reject_use", ModPartEnum.NAME,
|
||||||
|
"Not agreed to user guidelines, usage rejected",
|
||||||
|
"未同意用户使用准则,拒绝使用",
|
||||||
|
"未同意使用者準則,拒絕使用",
|
||||||
|
"未允用戶之約,拒用"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
addLang(
|
addLang(
|
||||||
LangKeyValue.ofKey("dglabgame.user_agreement.line1", ModPartEnum.NAME,
|
LangKeyValue.ofKey("dglabgame.user_agreement.line1", ModPartEnum.NAME,
|
||||||
"1. This mod is developed by §e§lR3944Realms §r, completely free and open source.",
|
"1. This mod is developed by §e§lR3944Realms §r, completely free and open source.",
|
||||||
|
|
@ -139,6 +148,183 @@ public enum DLGLangKey implements ILangKeyValueCollection {
|
||||||
// 6. 开发者不对任何人身伤害或财产损失负责。
|
// 6. 开发者不对任何人身伤害或财产损失负责。
|
||||||
// 6. Developers are not responsible for any personal injury or property damage.
|
// 6. Developers are not responsible for any personal injury or property damage.
|
||||||
|
|
||||||
|
initCommandKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initCommandKeys() {
|
||||||
|
// Server commands
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.server.started", ModPartEnum.NAME,
|
||||||
|
"DGLab WebSocket server started on port %s",
|
||||||
|
"DGLab WebSocket 服务器已在端口 %s 启动",
|
||||||
|
"DGLab WebSocket 伺服器已在連接埠 %s 啟動",
|
||||||
|
"DGLab WebSocket 伺服器已於埠 %s 啟"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.server.already_running", ModPartEnum.NAME,
|
||||||
|
"DGLab server is already running",
|
||||||
|
"DGLab 服务器已在运行中",
|
||||||
|
"DGLab 伺服器已在執行中",
|
||||||
|
"DGLab 伺服器已在運作中"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.server.stopped", ModPartEnum.NAME,
|
||||||
|
"DGLab server stopped",
|
||||||
|
"DGLab 服务器已关闭",
|
||||||
|
"DGLab 伺服器已關閉",
|
||||||
|
"DGLab 伺服器已停"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.server.not_running", ModPartEnum.NAME,
|
||||||
|
"DGLab server is not running",
|
||||||
|
"DGLab 服务器未在运行",
|
||||||
|
"DGLab 伺服器未在執行",
|
||||||
|
"DGLab 伺服器未啟"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.server.not_created", ModPartEnum.NAME,
|
||||||
|
"DGLab server has not been created yet",
|
||||||
|
"DGLab 服务器尚未创建",
|
||||||
|
"DGLab 伺服器尚未創建",
|
||||||
|
"DGLab 伺服器尚未建"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.server.status", ModPartEnum.NAME,
|
||||||
|
"Server status: %s, connected apps: %s",
|
||||||
|
"服务器状态: %s, 已连接应用: %s",
|
||||||
|
"伺服器狀態: %s, 已連線應用: %s",
|
||||||
|
"伺服器態: %s, 已連應用: %s"
|
||||||
|
));
|
||||||
|
|
||||||
|
// Client commands
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.client.created", ModPartEnum.NAME,
|
||||||
|
"DGLab client \"%s\" created (%s:%s)",
|
||||||
|
"DGLab 客户端 \"%s\" 已创建 (%s:%s)",
|
||||||
|
"DGLab 客戶端 \"%s\" 已創建 (%s:%s)",
|
||||||
|
"DGLab 客戶 \"%s\" 已建 (%s:%s)"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.client.removed", ModPartEnum.NAME,
|
||||||
|
"DGLab client \"%s\" removed",
|
||||||
|
"DGLab 客户端 \"%s\" 已移除",
|
||||||
|
"DGLab 客戶端 \"%s\" 已移除",
|
||||||
|
"DGLab 客戶 \"%s\" 已除"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.client.started", ModPartEnum.NAME,
|
||||||
|
"DGLab client \"%s\" started",
|
||||||
|
"DGLab 客户端 \"%s\" 已启动",
|
||||||
|
"DGLab 客戶端 \"%s\" 已啟動",
|
||||||
|
"DGLab 客戶 \"%s\" 已啟"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.client.stopped", ModPartEnum.NAME,
|
||||||
|
"DGLab client \"%s\" stopped",
|
||||||
|
"DGLab 客户端 \"%s\" 已关闭",
|
||||||
|
"DGLab 客戶端 \"%s\" 已關閉",
|
||||||
|
"DGLab 客戶 \"%s\" 已停"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.client.not_found", ModPartEnum.NAME,
|
||||||
|
"Client \"%s\" not found",
|
||||||
|
"未找到客户端 \"%s\"",
|
||||||
|
"未找到客戶端 \"%s\"",
|
||||||
|
"未見客戶 \"%s\""
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.client.none", ModPartEnum.NAME,
|
||||||
|
"No DGLab clients registered",
|
||||||
|
"没有已注册的 DGLab 客户端",
|
||||||
|
"沒有已註冊的 DGLab 客戶端",
|
||||||
|
"無已註之 DGLab 客戶"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.client.list", ModPartEnum.NAME,
|
||||||
|
"Registered clients: %s",
|
||||||
|
"已注册的客户端: %s",
|
||||||
|
"已註冊的客戶端: %s",
|
||||||
|
"已註客戶: %s"
|
||||||
|
));
|
||||||
|
|
||||||
|
// Device commands
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.invalid_channel", ModPartEnum.NAME,
|
||||||
|
"Invalid channel. Use A or B.",
|
||||||
|
"无效的通道。请使用 A 或 B。",
|
||||||
|
"無效的通道。請使用 A 或 B。",
|
||||||
|
"通道有誤,當用 A 或 B。"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.invalid_policy", ModPartEnum.NAME,
|
||||||
|
"Invalid policy. Use goto/set, increase/inc, or decrease/dec.",
|
||||||
|
"无效的策略。请使用 goto/set, increase/inc 或 decrease/dec。",
|
||||||
|
"無效的策略。請使用 goto/set, increase/inc 或 decrease/dec。",
|
||||||
|
"策略有誤,當用 goto/set、increase/inc 或 decrease/dec。"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.no_output", ModPartEnum.NAME,
|
||||||
|
"No active DGLab output available. Start the server or a client first.",
|
||||||
|
"没有可用的 DGLab 输出。请先启动服务器或客户端。",
|
||||||
|
"沒有可用的 DGLab 輸出。請先啟動伺服器或客戶端。",
|
||||||
|
"無可用之 DGLab 輸出。請先啟伺服器或客戶。"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.strength.sent", ModPartEnum.NAME,
|
||||||
|
"Strength [%s %s %s] sent to %s target(s)",
|
||||||
|
"强度 [%s %s %s] 已发送至 %s 个目标",
|
||||||
|
"強度 [%s %s %s] 已傳送至 %s 個目標",
|
||||||
|
"強度 [%s %s %s] 已送至 %s 標的"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.pulse.sent", ModPartEnum.NAME,
|
||||||
|
"Pulse waveform sent to channel %s (%s target(s))",
|
||||||
|
"脉冲波形已发送至通道 %s (%s 个目标)",
|
||||||
|
"脈衝波形已傳送至通道 %s (%s 個目標)",
|
||||||
|
"脈衝波形已送至通道 %s (%s 標的)"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.clear.sent", ModPartEnum.NAME,
|
||||||
|
"Clear command sent for channel %s (%s target(s))",
|
||||||
|
"清除指令已发送至通道 %s (%s 个目标)",
|
||||||
|
"清除指令已傳送至通道 %s (%s 個目標)",
|
||||||
|
"清除之令已送至通道 %s (%s 標的)"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("dglabgame.command.feedback.sent", ModPartEnum.NAME,
|
||||||
|
"Feedback value %s sent to %s target(s)",
|
||||||
|
"反馈值 %s 已发送至 %s 个目标",
|
||||||
|
"回饋值 %s 已傳送至 %s 個目標",
|
||||||
|
"回應值 %s 已送至 %s 標的"
|
||||||
|
));
|
||||||
|
|
||||||
|
// Management GUI
|
||||||
|
addLang(LangKeyValue.ofKey("key.dglabgame.management", ModPartEnum.NAME,
|
||||||
|
"Open Management", "打开管理", "開啟管理", "啟管理"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("gui.dglabgame.tab.qrcode", ModPartEnum.NAME,
|
||||||
|
"QR Code", "二维码", "QR碼", "二維碼"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("gui.dglabgame.tab.strength", ModPartEnum.NAME,
|
||||||
|
"Strength", "强度", "強度", "強度"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("gui.dglabgame.tab.waveform", ModPartEnum.NAME,
|
||||||
|
"Waveform", "波形", "波形", "波形"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("gui.dglabgame.tab.feedback", ModPartEnum.NAME,
|
||||||
|
"Feedback", "反馈", "回饋", "回應"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("gui.dglabgame.tab.server", ModPartEnum.NAME,
|
||||||
|
"Server", "服务器", "伺服器", "伺服器"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("gui.dglabgame.qrcode.copy", ModPartEnum.NAME,
|
||||||
|
"Copy QR URL to clipboard", "复制QR URL到剪贴板", "複製QR URL到剪貼板", "複QR URL"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("gui.dglabgame.strength.channel_a", ModPartEnum.NAME,
|
||||||
|
"Channel A", "通道A", "通道A", "通道甲"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("gui.dglabgame.strength.channel_b", ModPartEnum.NAME,
|
||||||
|
"Channel B", "通道B", "通道B", "通道乙"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("gui.dglabgame.waveform.channel", ModPartEnum.NAME,
|
||||||
|
"Channel:", "通道:", "通道:", "通道:"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("gui.dglabgame.feedback.send", ModPartEnum.NAME,
|
||||||
|
"Send Feedback:", "发送反馈:", "發送回饋:", "發回應:"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("gui.dglabgame.server.port", ModPartEnum.NAME,
|
||||||
|
"Port:", "端口:", "連接埠:", "埠:"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("gui.dglabgame.server.max_conn", ModPartEnum.NAME,
|
||||||
|
"Max:", "最大:", "最大:", "至多:"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("gui.dglabgame.server.status", ModPartEnum.NAME,
|
||||||
|
"Status: %s", "状态: %s", "狀態: %s", "態: %s"
|
||||||
|
));
|
||||||
|
addLang(LangKeyValue.ofKey("gui.dglabgame.client.label", ModPartEnum.NAME,
|
||||||
|
"Client:", "客户端:", "客戶端:", "客戶:"
|
||||||
|
));
|
||||||
|
|
||||||
}
|
}
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user