Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Beta40 #98

Merged
merged 52 commits into from
Feb 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
1479feb
beta9
Hoshinonyaruko Jan 26, 2024
4a6f523
beta11
Hoshinonyaruko Jan 26, 2024
8739198
beta11
Hoshinonyaruko Jan 26, 2024
d9e0844
beta13
Hoshinonyaruko Jan 26, 2024
ab96bf7
beta14
Hoshinonyaruko Jan 26, 2024
9b7bf0e
beta12
Hoshinonyaruko Jan 26, 2024
7c66e7d
beta13
Hoshinonyaruko Jan 26, 2024
eb0b186
beta15
Hoshinonyaruko Jan 26, 2024
122de8b
beta16
Hoshinonyaruko Jan 26, 2024
5e4903f
beta17
Hoshinonyaruko Jan 26, 2024
7a82cfb
beta18
Hoshinonyaruko Jan 27, 2024
ecc8263
mergefix
Hoshinonyaruko Jan 27, 2024
d0a0a85
beta19
Hoshinonyaruko Jan 27, 2024
afcb856
beta20
Hoshinonyaruko Jan 27, 2024
fafe0f9
beta20
Hoshinonyaruko Jan 27, 2024
397d4c7
beta21
Hoshinonyaruko Jan 27, 2024
c00e1a8
fixmerge
Hoshinonyaruko Jan 27, 2024
42ed202
add_playermanager_api
Hoshinonyaruko Jan 27, 2024
31a6771
beta22
Hoshinonyaruko Jan 27, 2024
050d359
beta22
Hoshinonyaruko Jan 27, 2024
939e818
beta23
Hoshinonyaruko Jan 28, 2024
19cf927
merge
Hoshinonyaruko Jan 28, 2024
8073f3a
beta24
Hoshinonyaruko Jan 29, 2024
fdd6016
mergechanges
Hoshinonyaruko Jan 29, 2024
b167455
beta25
Hoshinonyaruko Jan 30, 2024
844698b
merge
Hoshinonyaruko Jan 30, 2024
f5c8d82
beta26
Hoshinonyaruko Jan 30, 2024
2d5e94d
merge
Hoshinonyaruko Jan 30, 2024
3076085
beta27
Hoshinonyaruko Jan 30, 2024
a8a67ed
beta28
Hoshinonyaruko Jan 31, 2024
4c954fa
beta28
Hoshinonyaruko Jan 31, 2024
2f9063e
beta28
Hoshinonyaruko Jan 31, 2024
cd6fad7
beta29
Hoshinonyaruko Jan 31, 2024
2651176
beta29
Hoshinonyaruko Jan 31, 2024
265b5e3
beta30
Hoshinonyaruko Jan 31, 2024
8aac47a
beta31
Hoshinonyaruko Feb 2, 2024
a559fa2
beta31
Hoshinonyaruko Feb 2, 2024
f5bb66a
beta32
Hoshinonyaruko Feb 2, 2024
44fac8f
beta33
Hoshinonyaruko Feb 6, 2024
a44ef68
merge
Hoshinonyaruko Feb 6, 2024
e731f93
beta34
Hoshinonyaruko Feb 8, 2024
c8921a1
beta34
Hoshinonyaruko Feb 8, 2024
e6b4a3e
beta35
Hoshinonyaruko Feb 8, 2024
ac77292
merge
Hoshinonyaruko Feb 8, 2024
3992e84
beta35
Hoshinonyaruko Feb 8, 2024
d19fc5c
beta36
Hoshinonyaruko Feb 8, 2024
ff271bc
merge
Hoshinonyaruko Feb 8, 2024
a451334
beta37
Hoshinonyaruko Feb 18, 2024
6e4f28c
beta37
Hoshinonyaruko Feb 18, 2024
89d6c06
beta38
Hoshinonyaruko Feb 18, 2024
75002bc
beta39
Hoshinonyaruko Feb 18, 2024
e808a36
beta40
Hoshinonyaruko Feb 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 98 additions & 13 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ type Config struct {
WhiteCheckTime int `json:"whiteCheckTime"` // 白名单检测时间
SaveDeleteDays int `json:"saveDeleteDays"` // 存档删除时间
SteamCmdPath string `json:"steamCmdPath"` // 自定义steamcmd路径
EnableUe4Debug bool `json:"enableUe4Debug"` // 是否开启UE4 Debug窗口
EnableEngineSetting bool `json:"enableEngineSetting"` // 是否开启引擎设置
}

// 默认配置
Expand All @@ -83,6 +85,8 @@ var defaultConfig = Config{
CheckInterval: 30, // 30 秒
WebuiPort: "52000", // Webui 端口号
AutolaunchWebui: true,
EnableUe4Debug: false,
EnableEngineSetting: true,
BackupInterval: 1800, // 30 分钟
MemoryCheckInterval: 30, // 30 秒
MemoryUsageThreshold: 80, // 80%
Expand Down Expand Up @@ -432,23 +436,31 @@ func AutoConfigurePaths(config *Config) error {
return err
}
}
engine, err := ReadEngineSettings(config)
if err != nil {
log.Printf("解析游戏engine.ini出错,错误%v", err)
if config.EnableEngineSetting {
engine, err := ReadEngineSettings(config)
if err != nil {
log.Printf("解析游戏engine.ini出错,错误%v", err)

} else {
config.Engine = engine
log.Println("从游戏engine.ini解析配置成功.")
log.Printf("从游戏engine.ini解析配置成功.%v", config.Engine)
} else {
config.Engine = engine
log.Println("从游戏engine.ini解析配置成功.")
log.Printf("从游戏engine.ini解析配置成功.%v", config.Engine)

// 将更新后的配置写回文件
updatedConfig, err := json.MarshalIndent(config, "", " ")
if err != nil {
return err
// 将更新后的配置写回文件
updatedConfig, err := json.MarshalIndent(config, "", " ")
if err != nil {
return err
}
err = os.WriteFile("config.json", updatedConfig, 0644)
if err != nil {
return err
}
}
err = os.WriteFile("config.json", updatedConfig, 0644)
} else {
// 调用RemoveEngineSettings函数
err := RemoveEngineSettings(config)
if err != nil {
return err
log.Printf("从游戏engine.ini删除配置失败.%v\n", err)
}
}

Expand Down Expand Up @@ -846,6 +858,43 @@ func WriteEngineSettings(config *Config, engine *Engine) error {
return os.WriteFile(iniPath, []byte(content), 0644)
}

// RemoveEngineSettings 从INI文件中删除Engine结构体的数据
func RemoveEngineSettings(config *Config) error {
var iniPath string

// 根据操作系统选择不同的路径
switch runtime.GOOS {
case "windows":
iniPath = filepath.Join(config.GameSavePath, "Config", "WindowsServer", "Engine.ini")
case "linux":
iniPath = filepath.Join(config.GameSavePath, "Config", "LinuxServer", "Engine.ini")
default:
iniPath = filepath.Join(config.GameSavePath, "Config", "LinuxServer", "Engine.ini")
}

// 读取INI文件的所有内容
fileContent, err := ioutil.ReadFile(iniPath)
if err != nil {
return err
}

// 将文件内容转换为字符串
content := string(fileContent)

// 定义要删除的节的列表
sectionsToRemove := []string{
"/script/engine.player",
"/script/socketsubsystemepic.epicnetdriver",
"/script/engine.engine",
}

// 删除指定的节
updatedContent := removeIniSections(content, sectionsToRemove)

// 将更新后的内容写回文件
return os.WriteFile(iniPath, []byte(updatedContent), 0644)
}

// updateIniSection 更新或添加INI文件中的特定section
func updateIniSection(content, sectionName string, data interface{}) string {
// 将结构体转换为键值对映射
Expand Down Expand Up @@ -967,3 +1016,39 @@ func structToMap(data interface{}) map[string]string {

return kvMap
}

// removeIniSections 从INI文件内容中删除指定的节
func removeIniSections(content string, sectionsToRemove []string) string {
var lines = strings.Split(content, "\n")
var updatedLines []string
var inSectionToRemove bool

for _, line := range lines {
trimmedLine := strings.TrimSpace(line)
// 检查当前行是否标记了新的节的开始
if strings.HasPrefix(trimmedLine, "[") && strings.HasSuffix(trimmedLine, "]") {
sectionName := trimmedLine[1 : len(trimmedLine)-1] // 移除括号获取节名
inSectionToRemove = contains(sectionsToRemove, sectionName)
if !inSectionToRemove {
// 如果当前节不在要删除的列表中,保留这一行
updatedLines = append(updatedLines, line)
}
} else if !inSectionToRemove {
// 如果当前不在要删除的节中,保留这一行
updatedLines = append(updatedLines, line)
}
// 如果inSectionToRemove为true,则自动跳过这一行,不将其添加到updatedLines中
}

return strings.Join(updatedLines, "\n")
}

// contains 检查字符串切片中是否包含特定的字符串
func contains(slice []string, val string) bool {
for _, item := range slice {
if item == val {
return true
}
}
return false
}
24 changes: 23 additions & 1 deletion front/palworld-front/src/pages/IndexView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@
@click="restartServer"
class="q-mt-md"
/>
<!-- 答疑按钮 -->
<q-btn
color="secondary"
label="遇到问题,答疑按钮"
@click="getGroupLink"
class="q-mt-md"
/>
<!-- 文本输入框 -->
<q-input
filled
Expand Down Expand Up @@ -69,14 +76,24 @@
/>
<q-toggle
v-model="config.useDll"
label="自动注入UE4SS和可输入命令控制台DLL"
label="自动注入UE4SS和可输入命令控制台DLL(发中文rcon)"
class="q-my-md"
/>
<q-toggle
v-model="config.gameService"
label="是否采用systemctl方式管理游戏服务"
class="q-my-md"
/>
<q-toggle
v-model="config.enableUe4Debug"
label="是否开启UE4窗口(关闭可以解决闪退,内存占用问题)"
class="q-my-md"
/>
<q-toggle
v-model="config.enableEngineSetting"
label="是否启用引擎配置,部分电脑修改引擎配置会卡顿,可关闭"
class="q-my-md"
/>
<q-input
filled
v-model="config.maintenanceWarningMessage"
Expand Down Expand Up @@ -1050,7 +1067,7 @@
uin: Number,
});

const players = ref([]);

Check warning on line 1070 in front/palworld-front/src/pages/IndexView.vue

View workflow job for this annotation

GitHub Actions / Build on darwin for arm64

'players' is assigned a value but never used

Check warning on line 1070 in front/palworld-front/src/pages/IndexView.vue

View workflow job for this annotation

GitHub Actions / Build on linux for amd64

'players' is assigned a value but never used

Check warning on line 1070 in front/palworld-front/src/pages/IndexView.vue

View workflow job for this annotation

GitHub Actions / Build on darwin for amd64

'players' is assigned a value but never used

Check warning on line 1070 in front/palworld-front/src/pages/IndexView.vue

View workflow job for this annotation

GitHub Actions / Build on linux for arm64

'players' is assigned a value but never used

Check warning on line 1070 in front/palworld-front/src/pages/IndexView.vue

View workflow job for this annotation

GitHub Actions / Build on windows for amd64

'players' is assigned a value but never used

const status = ref(null); // 假设 ProcessInfo 是一个对象,这里使用 null 作为初始值

Expand All @@ -1064,11 +1081,11 @@
const showDifficultyTooltip = ref(false);
const showDeathPenaltyTooltip = ref(false);

const toggleTooltip = (type) => {

Check warning on line 1084 in front/palworld-front/src/pages/IndexView.vue

View workflow job for this annotation

GitHub Actions / Build on darwin for arm64

'type' is defined but never used

Check warning on line 1084 in front/palworld-front/src/pages/IndexView.vue

View workflow job for this annotation

GitHub Actions / Build on linux for amd64

'type' is defined but never used

Check warning on line 1084 in front/palworld-front/src/pages/IndexView.vue

View workflow job for this annotation

GitHub Actions / Build on darwin for amd64

'type' is defined but never used

Check warning on line 1084 in front/palworld-front/src/pages/IndexView.vue

View workflow job for this annotation

GitHub Actions / Build on linux for arm64

'type' is defined but never used

Check warning on line 1084 in front/palworld-front/src/pages/IndexView.vue

View workflow job for this annotation

GitHub Actions / Build on windows for amd64

'type' is defined but never used
showDeathPenaltyTooltip.value = !showDeathPenaltyTooltip.value;
};

const toggleTooltip2 = (type) => {

Check warning on line 1088 in front/palworld-front/src/pages/IndexView.vue

View workflow job for this annotation

GitHub Actions / Build on darwin for arm64

'type' is defined but never used

Check warning on line 1088 in front/palworld-front/src/pages/IndexView.vue

View workflow job for this annotation

GitHub Actions / Build on linux for amd64

'type' is defined but never used

Check warning on line 1088 in front/palworld-front/src/pages/IndexView.vue

View workflow job for this annotation

GitHub Actions / Build on darwin for amd64

'type' is defined but never used

Check warning on line 1088 in front/palworld-front/src/pages/IndexView.vue

View workflow job for this annotation

GitHub Actions / Build on linux for arm64

'type' is defined but never used

Check warning on line 1088 in front/palworld-front/src/pages/IndexView.vue

View workflow job for this annotation

GitHub Actions / Build on windows for amd64

'type' is defined but never used
showDifficultyTooltip.value = !showDifficultyTooltip.value;
};

Expand Down Expand Up @@ -1266,6 +1283,11 @@

//服务器检测

const getGroupLink = () => {
window.location.href =
'https://qm.qq.com/cgi-bin/qm/qr?k=7aDJFyxLC6a450LMZfzG9Q1lwWy2veQj&jump_from=webapi&authKey=Im38dkervx6ISKg78NudQZgZnZv/O4bmb8f8CFrgMmJKY+MH5LsVNJ+KdJB5byY1';
};

async function updateStatus() {
try {
// 移除了 $q.loadingBar 的调用
Expand Down
4 changes: 2 additions & 2 deletions front/palworld-front/src/pages/LoginView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ async function login() {
void $router.push('/index');
} else {
loginError.value =
'登录失败,请检查用户名和密码。请查看程序窗口输出的用户名密码,或在同目录下config.json中搜索:serverName、adminPassword 对应用户名,密码。';
'Login failed, please check the username and password. Please refer to the program\'s command line window for the default username and password.\n登录失败,请检查用户名和密码。请查看程序命令行窗口输出的默认用户名密码。';
// 显示通知
$q.notify({
color: 'negative',
Expand All @@ -95,7 +95,7 @@ async function login() {
}
} catch (err) {
loginError.value =
'登录失败,请检查用户名和密码。请查看程序窗口输出的用户名密码,或在同目录下config.json中搜索:serverName、adminPassword 对应用户名,密码。';
'Login failed, please check the username and password. Please refer to the program\'s command line window for the default username and password.\n登录失败,请检查用户名和密码。请查看程序命令行窗口输出的默认用户名密码。';
$q.notify({
color: 'negative',
position: 'top',
Expand Down
148 changes: 142 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"embed"
"encoding/pem"
"fmt"
"io"
"io/fs"
"log"
"math/big"
Expand All @@ -17,7 +18,9 @@ import (
"os"
"os/exec"
"os/signal"
"path/filepath"
"runtime"
"strings"
"syscall"
"time"

Expand Down Expand Up @@ -48,6 +51,71 @@ func main() {
//给程序整个标题
sys.SetTitle(jsonconfig.Title + " 作者 早苗狐 答疑群:587997911")

//为小白和萌新贴心打造的引导启动流程,解决小白不会寻找路径,不会复制文件的问题。点击即用,友好方便。
if runtime.GOOS == "windows" {
//检查程序是否运行在合适目录
if _, err := os.Stat("PalServer.exe"); os.IsNotExist(err) {
// PalServer.exe不存在,查找PalServer-Win64-Test-Cmd.exe的路径
cmd := exec.Command("cmd", "/C", "wmic process where name='PalServer-Win64-Test-Cmd.exe' get ExecutablePath")
output, err := cmd.Output()
if err != nil {
fmt.Println("Failed to execute command:", err)
return
}

outputStr := string(output)
if !strings.Contains(outputStr, "ExecutablePath") {
fmt.Println("PalServer-Win64-Test-Cmd.exe not found")
fmt.Println("Notice:Please restart this program after launching the game server, and the installation will be completed automatically, releasing a launch icon to the desktop.")
fmt.Println("请打开游戏服务端后再次运行本程序,将会自动完成安装,释放启动图标到桌面。")
showMessage("提示", "请打开游戏服务端保持运行后的同时运行本程序,\n将会自动寻找游戏路径,\n自动完成安装,并释放启动图标到桌面。\n请到桌面使用StartPalWorld.bat启动我。\nNotice:Please restart this program after launching the game server, and the installation will be completed automatically, releasing a launch icon to the desktop.")
return
}

lines := strings.Split(outputStr, "\n")
for _, line := range lines {
if strings.TrimSpace(line) != "" && !strings.Contains(line, "ExecutablePath") {
exePath := strings.TrimSpace(line)
// 获取到的exe路径向上移动到PalServer这个级别
targetDir := filepath.Dir(filepath.Dir(filepath.Dir(filepath.Dir(exePath)))) // 假设路径格式没有变化
targetExePath := filepath.Join(targetDir, "palworld-go.exe")

// 复制自身到目标目录
self, _ := os.Executable()
target, err := os.Create(targetExePath)
if err != nil {
fmt.Println("Failed to create target file:", err)
return
}
defer target.Close()

source, err := os.Open(self)
if err != nil {
fmt.Println("Failed to open source file:", err)
return
}
defer source.Close()

_, err = io.Copy(target, source)
if err != nil {
fmt.Println("Failed to copy file:", err)
return
}

//创建启动脚本
createBATScript(targetDir, "palworld-go.exe")

fmt.Println("PalWorld-Go setup completed successfully.")
showMessage("提示", "现在请关闭服务端窗口!,并在桌面找到脚本启动palworld-go(会自动打开服务端).\n安装成功,请从桌面名为 StartPalWorld.bat 的脚本图标启动pal-go面板。\n请在5秒内点击确认按钮~确保文件能够释放成功~\nPalWorld-Go setup completed successfully. please launch palworld-go form the desktop.")
deleteSelfAndConfigs()
return
}
}
} else {
fmt.Println("PalServer.exe exists in the current directory.")
}
}

// 设置监控和自动重启
supervisor := NewSupervisor(jsonconfig)
go supervisor.Start()
Expand Down Expand Up @@ -237,12 +305,14 @@ func main() {
} else {
fmt.Println("Game world settings saved successfully.")
}
//保存引擎配置
err = config.WriteEngineSettings(&jsonconfig, jsonconfig.Engine)
if err != nil {
fmt.Println("Error writing Engine settings:", err)
} else {
fmt.Println("Engine settings saved successfully.")
if jsonconfig.EnableEngineSetting {
//保存引擎配置
err = config.WriteEngineSettings(&jsonconfig, jsonconfig.Engine)
if err != nil {
fmt.Println("Error writing Engine settings:", err)
} else {
fmt.Println("Engine settings saved successfully.")
}
}
}
}()
Expand Down Expand Up @@ -355,3 +425,69 @@ func generateRandomString(n int) string {
}
return string(b)
}

func showMessage(title, text string) error {
// PowerShell脚本来显示消息框
psScript := `
Add-Type -AssemblyName PresentationFramework
[System.Windows.MessageBox]::Show('` + text + `', '` + title + `')
`
cmd := exec.Command("powershell", "-Command", psScript)
err := cmd.Start() // 使用Start而不是Run,以非阻塞方式执行
if err != nil {
return err
}
return nil
}

func createBATScript(targetDir, targetExeName string) error {
desktopPathCmd := exec.Command("powershell", "-Command", "[System.Environment]::GetFolderPath('Desktop')")
desktopPathBytes, err := desktopPathCmd.Output()
if err != nil {
return fmt.Errorf("failed to get desktop path: %v", err)
}
desktopPath := string(desktopPathBytes)
desktopPath = desktopPath[:len(desktopPath)-2] // 移除末尾的\r\n

batContent := fmt.Sprintf(`
@echo off
cd /d "%s"
start "" "%s"
`, targetDir, filepath.Join(targetDir, targetExeName))

batFilePath := filepath.Join(desktopPath, "StartPalWorld.bat")
err = os.WriteFile(batFilePath, []byte(batContent), 0644)
if err != nil {
return fmt.Errorf("failed to create BAT file: %v", err)
}

return nil
}

func deleteSelfAndConfigs() error {
exePath, err := os.Executable()
if err != nil {
return fmt.Errorf("failed to get executable path: %v", err)
}
dir := filepath.Dir(exePath)

// 构造PowerShell脚本命令
psScript := fmt.Sprintf(`
Start-Sleep -Seconds 5
Remove-Item '%s' -Force
Remove-Item '%s\\config.json' -Force
Remove-Item '%s\\config.ini' -Force
`, exePath, dir, dir)

cmd := exec.Command("powershell", "-Command", psScript)

// 开始执行PowerShell命令,不等待其完成
if err := cmd.Start(); err != nil {
return fmt.Errorf("failed to start PowerShell script: %v", err)
}

// 退出当前程序,让PowerShell脚本有机会删除文件
os.Exit(0)

return nil
}
Binary file modified mod/embeds/UE4SS.dll
Binary file not shown.
Binary file added mod/embeds/dwmapi.dll
Binary file not shown.
Loading
Loading