mirror of
https://github.com/EasyTier/EasytierGame.git
synced 2025-05-19 10:27:56 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab67ba94a3 | ||
|
|
8e6f8d602e |
+2
-4
@@ -10,7 +10,5 @@ dist
|
||||
.idea
|
||||
.vscode
|
||||
release
|
||||
src-tauri/easytier-cli.exe
|
||||
src-tauri/easytier-core.exe
|
||||
src-tauri/Packet.dll
|
||||
src-tauri/wintun.dll
|
||||
|
||||
src-tauri/easytier/logs
|
||||
@@ -43,7 +43,7 @@ Releases: [https://github.com/EasyTier/EasytierGame/releases](https://github.c
|
||||
|
||||
- 1.1.8 新增了 生成 easytier/config.json 的功能 会将一部分配置写入到 config.json 文件中,方便用户自定义配置,你可以在高级设置里启用和关闭这个功能(默认关闭)
|
||||
**需要注意的是,如果config.json存在,每次启动easytierGame默认按照config.json的配置为准**
|
||||
**你可以查看 config_template.json 里的注释进行配置**
|
||||
**解压zip后你可以查看 easytier/config_template.json 里的注释进行配置**
|
||||

|
||||
|
||||
## 特性
|
||||
|
||||
+41
-12
@@ -1,16 +1,45 @@
|
||||
import { BaseDirectory, writeTextFile } from "@tauri-apps/plugin-fs";
|
||||
import useMainStore from "@/stores/index";
|
||||
import { ElMessage } from "element-plus";
|
||||
export const updateConfigJson = async () => {
|
||||
|
||||
import { uniq, intersection, isNil } from "lodash-es";
|
||||
export const updateConfigJson = async (configJsonSeverUrl: Array<string> | string | null | undefined) => {
|
||||
const mainStore = useMainStore();
|
||||
const path = import.meta.env.VITE_CONFIG_FILE_NAME;
|
||||
try {
|
||||
const { proxyNetworks, autoStart, relayAllPeerrpc, coonectAfterStart, multiThread, enablExitNode, useSmoltcp, saveErrorLog, logLevel, ...otherConfig } =
|
||||
mainStore.config;
|
||||
await writeTextFile(path, JSON.stringify(otherConfig, null, 4), { baseDir: BaseDirectory.Resource });
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
ElMessage.error(`更新config.json失败`);
|
||||
}
|
||||
}
|
||||
const path = import.meta.env.VITE_CONFIG_FILE_NAME;
|
||||
if (isNil(configJsonSeverUrl)) {
|
||||
configJsonSeverUrl = [];
|
||||
}
|
||||
const isArray = Array.isArray(configJsonSeverUrl);
|
||||
const isString = typeof configJsonSeverUrl === "string";
|
||||
try {
|
||||
const {
|
||||
proxyNetworks,
|
||||
autoStart,
|
||||
relayAllPeerrpc,
|
||||
coonectAfterStart,
|
||||
multiThread,
|
||||
enablExitNode,
|
||||
useSmoltcp,
|
||||
saveErrorLog,
|
||||
logLevel,
|
||||
serverUrl,
|
||||
...otherConfig
|
||||
} = mainStore.config;
|
||||
let writeServerUrl: Array<string> | string = serverUrl;
|
||||
if (isArray) {
|
||||
writeServerUrl = intersection(
|
||||
uniq([serverUrl, ...configJsonSeverUrl]).filter(boolean => boolean),
|
||||
mainStore.basePeers
|
||||
);
|
||||
}
|
||||
if (isString && configJsonSeverUrl) {
|
||||
writeServerUrl = intersection(
|
||||
uniq([serverUrl, ...(configJsonSeverUrl as string).split(",")]).filter(boolean => boolean),
|
||||
mainStore.basePeers
|
||||
).join(",");
|
||||
}
|
||||
await writeTextFile(path, JSON.stringify({ serverUrl: writeServerUrl, ...otherConfig }, null, 4), { baseDir: BaseDirectory.Resource });
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
ElMessage.error(`更新config.json失败`);
|
||||
}
|
||||
};
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
"private": true,
|
||||
"author": "leizi97",
|
||||
"description": "A simple network initiator based on Easytier",
|
||||
"version": "1.1.8",
|
||||
"version": "1.1.9",
|
||||
"scripts": {
|
||||
"dev": "nuxt dev --dotenv env/.env.dev --host 0.0.0.0",
|
||||
"build": "nuxt generate --dotenv env/.env.prod"
|
||||
|
||||
+40
-9
@@ -1,19 +1,12 @@
|
||||
<template>
|
||||
<div class="h-full overflow-auto flex flex-col items-start px-[25px]">
|
||||
<div><ElCheckbox v-model="mainStore.config.disableIpv6">不使用IPv6</ElCheckbox></div>
|
||||
<div class="flex items-center gap-[10px]">
|
||||
<ElCheckbox v-model="mainStore.config.devName">自定义网卡名</ElCheckbox>
|
||||
<ElInput
|
||||
maxlength="10"
|
||||
v-model="mainStore.config.devNameValue"
|
||||
placeholder="请输入网卡名"
|
||||
/>
|
||||
</div>
|
||||
<div><ElCheckbox v-model="mainStore.config.disbleListenner">不监听任何端口,只连接到对等节点</ElCheckbox></div>
|
||||
<div class="flex items-center gap-[15px] flex-nowrap">
|
||||
<ElCheckbox v-model="mainStore.config.saveErrorLog">输出日志到本地</ElCheckbox>
|
||||
<div class="w-[140px]">
|
||||
<ElSelect
|
||||
size="small"
|
||||
v-model="mainStore.config.logLevel"
|
||||
placeholder="请选择日志等级"
|
||||
class="ml-[5px]"
|
||||
@@ -44,12 +37,49 @@
|
||||
</ElButton>
|
||||
</div>
|
||||
|
||||
<ElDivider />
|
||||
<div class="flex items-center gap-[10px]">
|
||||
<ElCheckbox v-model="mainStore.config.devName">自定义网卡名</ElCheckbox>
|
||||
<ElInput
|
||||
size="small"
|
||||
maxlength="10"
|
||||
v-model="mainStore.config.devNameValue"
|
||||
placeholder="请输入网卡名"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center gap-[10px]">
|
||||
<ElCheckbox v-model="mainStore.config.enableNetCardMetric">自定义easytier网卡跃点</ElCheckbox>
|
||||
<ElInputNumber
|
||||
controls-position="right"
|
||||
:min="1"
|
||||
:value-on-clear="1"
|
||||
:max="9999"
|
||||
:step="1"
|
||||
:precision="0"
|
||||
size="small"
|
||||
v-model="mainStore.config.netCardMetricValue"
|
||||
placeholder="请选择跃点数"
|
||||
/>
|
||||
<ElTooltip content="设置easytier网卡的跃点,提升网卡优先级,跃点越小,网卡优先级越高">
|
||||
<ElIcon><QuestionFilled /></ElIcon>
|
||||
</ElTooltip>
|
||||
</div>
|
||||
<div>
|
||||
<ElText
|
||||
size="small"
|
||||
type="warning"
|
||||
>
|
||||
(不使用自定义网卡名,那么联机时默认会生成一个名为 "et_xxx" 的网卡,也可以使用 “设置跃点” 功能,除非你启用了下面的功能)
|
||||
</ElText>
|
||||
</div>
|
||||
<div><ElCheckbox v-model="mainStore.config.noTun">不创建TUN设备(网卡),可以使用子网代理访问节点</ElCheckbox></div>
|
||||
|
||||
<ElDivider />
|
||||
<div><ElCheckbox v-model="mainStore.config.enablExitNode">允许此节点成为出口节点</ElCheckbox></div>
|
||||
<div><ElCheckbox v-model="mainStore.config.disableEncryption">禁用对等节点通信的加密,默认为false,必须与对等节点相同</ElCheckbox></div>
|
||||
<div><ElCheckbox v-model="mainStore.config.multiThread">使用多线程运行时,默认为单线程</ElCheckbox></div>
|
||||
<ElDivider />
|
||||
<div><ElCheckbox v-model="mainStore.config.noTun">不创建TUN设备,可以使用子网代理访问节点</ElCheckbox></div>
|
||||
|
||||
<div><ElCheckbox v-model="mainStore.config.useSmoltcp">为子网代理启用smoltcp堆栈</ElCheckbox></div>
|
||||
<div><ElCheckbox v-model="mainStore.config.latencyfirst">延迟优先模式,将尝试使用最低延迟路径转发流量,默认使用最短路径</ElCheckbox></div>
|
||||
<div><ElCheckbox v-model="mainStore.config.disableUdpHolePunching">禁用UDP打洞功能</ElCheckbox></div>
|
||||
@@ -60,6 +90,7 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import useMainStore from "@/stores/index";
|
||||
import { QuestionFilled } from "@element-plus/icons-vue";
|
||||
import { getCurrentWindow } from "@tauri-apps/api/window";
|
||||
import { resourceDir as getResourceDir, join } from "@tauri-apps/api/path";
|
||||
import { Command } from "@tauri-apps/plugin-shell";
|
||||
|
||||
+64
-25
@@ -59,6 +59,7 @@
|
||||
<ElSelect
|
||||
allow-create
|
||||
filterable
|
||||
placeholder="请选择服务器地址"
|
||||
default-first-option
|
||||
v-model="config.serverUrl"
|
||||
@change="handleServerUrlChange"
|
||||
@@ -88,14 +89,18 @@
|
||||
:label="item"
|
||||
:value="item"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
<span style="float: left">{{ item }}</span>
|
||||
<ElButton
|
||||
@click.stop="handleDeleteServerUrl(item)"
|
||||
round
|
||||
:icon="Delete"
|
||||
type="danger"
|
||||
></ElButton>
|
||||
<div class="flex items-center gap-[20px] overflow-hidden flex-nowrap max-w-[calc(100vw-62px)]">
|
||||
<ElTooltip :content="item">
|
||||
<p class="truncate">{{ item }}</p>
|
||||
</ElTooltip>
|
||||
<div class="flex-shrink-0 ml-auto">
|
||||
<ElButton
|
||||
@click.stop="handleDeleteServerUrl(item)"
|
||||
round
|
||||
:icon="Delete"
|
||||
type="danger"
|
||||
></ElButton>
|
||||
</div>
|
||||
</div>
|
||||
</ElOption>
|
||||
</ElSelect>
|
||||
@@ -407,6 +412,7 @@
|
||||
import { readDir, exists, mkdir, BaseDirectory, readTextFile } from "@tauri-apps/plugin-fs";
|
||||
import { updateConfigJson } from "~/composables/configJson";
|
||||
import { writeText, readText } from "@tauri-apps/plugin-clipboard-manager";
|
||||
import { sortedUniq, uniq } from "lodash-es";
|
||||
import { bounce } from "~/utils";
|
||||
|
||||
let is_close = false;
|
||||
@@ -436,7 +442,8 @@
|
||||
isSuccessGetIp: false,
|
||||
startLoading: false,
|
||||
isStart: false,
|
||||
connectionSuccess: false
|
||||
connectionSuccess: false,
|
||||
configJsonSeverUrl: "" // 本地保存一次,用于回填config.json
|
||||
});
|
||||
|
||||
const configStart = reactive<{ list: Array<{ path: string; name: string }>; [key: string]: any }>({
|
||||
@@ -474,11 +481,11 @@
|
||||
}
|
||||
newBasePeers.splice(idx, 1);
|
||||
}
|
||||
mainStore.basePeers = [...new Set([...newBasePeers])];
|
||||
mainStore.basePeers = uniq([...newBasePeers]);
|
||||
};
|
||||
|
||||
const handleServerUrlChange = () => {
|
||||
mainStore.basePeers = [...new Set([config.serverUrl, ...mainStore.basePeers])];
|
||||
mainStore.basePeers = uniq([config.serverUrl, ...mainStore.basePeers]);
|
||||
};
|
||||
|
||||
const listenObj: { [key: string]: any } = {
|
||||
@@ -493,6 +500,7 @@
|
||||
if (event.payload) {
|
||||
data.startLoading = false;
|
||||
let ipv4 = /dhcp ip changed. old: None, new: Some\((\d+\.\d+\.\d+\.\d+).*\)/g.exec(event.payload as string)?.[1];
|
||||
let devName = /tun device ready. dev: (.*)/g.exec(event.payload as string)?.[1];
|
||||
if (config.dhcp || mainStore.configStartEnable) {
|
||||
if (ipv4) {
|
||||
config.ipv4 = ipv4;
|
||||
@@ -507,6 +515,26 @@
|
||||
await setTrayTooltip(tray, `IP: ${config.ipv4}`);
|
||||
}
|
||||
}
|
||||
if (
|
||||
devName &&
|
||||
mainStore.config.enableNetCardMetric &&
|
||||
mainStore.config.netCardMetricValue &&
|
||||
mainStore.config.netCardMetricValue >= 1 &&
|
||||
mainStore.config.netCardMetricValue <= 9999
|
||||
) {
|
||||
try {
|
||||
const output = await Command.create(
|
||||
"netsh",
|
||||
["interface", "ipv4", "set", "interface", devName, "metric=", `${mainStore.config.netCardMetricValue}`],
|
||||
{
|
||||
encoding: "gb2312"
|
||||
}
|
||||
).execute();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
ElMessage.error("跃点设置失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
const logArr = data.log.split("\n");
|
||||
const start = logArr.length > 1000 ? logArr.length - 1000 : 0;
|
||||
@@ -667,14 +695,28 @@
|
||||
const regex2 = /(,?)\s*\/\/.*(?=\n|$|\r\n)/gm;
|
||||
const resultStr = guiJsonStr.replace(regex, "").replace(regex2, "$1");
|
||||
const guiJson = JSON.parse(resultStr);
|
||||
let saveServerUrl = "";
|
||||
if (guiJson.serverUrl) {
|
||||
if (Array.isArray(guiJson.serverUrl)) {
|
||||
mainStore.basePeers = uniq([...guiJson.serverUrl, ...mainStore.basePeers]);
|
||||
}
|
||||
if (typeof guiJson.serverUrl === "string") {
|
||||
mainStore.basePeers = uniq([...guiJson.serverUrl.split(","), ...mainStore.basePeers]);
|
||||
}
|
||||
saveServerUrl = mainStore.basePeers[0] || "";
|
||||
} else {
|
||||
saveServerUrl = mainStore.basePeers.length > 0 ? mainStore.basePeers[0] || "" : "";
|
||||
}
|
||||
data.configJsonSeverUrl = guiJson.serverUrl;
|
||||
mainStore.$patch({
|
||||
config: {
|
||||
...guiJson,
|
||||
...mainStore.config,
|
||||
...guiJson
|
||||
serverUrl: saveServerUrl
|
||||
}
|
||||
});
|
||||
if (guiJson.serverUrl) {
|
||||
mainStore.basePeers = [...new Set([guiJson.serverUrl, ...mainStore.basePeers])];
|
||||
if (mainStore.createConfigInEasytier) {
|
||||
await updateConfigJson(data.configJsonSeverUrl);
|
||||
}
|
||||
} catch (err) {
|
||||
ElMessage.error(`config.json格式错误`);
|
||||
@@ -682,16 +724,13 @@
|
||||
}
|
||||
}
|
||||
const b = bounce(600);
|
||||
mainStore.$subscribe(
|
||||
(...a) => {
|
||||
if (mainStore.createConfigInEasytier) {
|
||||
b(async () => {
|
||||
await updateConfigJson();
|
||||
});
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
mainStore.$subscribe((...a) => {
|
||||
if (mainStore.createConfigInEasytier) {
|
||||
b(async () => {
|
||||
await updateConfigJson(data.configJsonSeverUrl);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let logsTimer: NodeJS.Timeout | null = null;
|
||||
@@ -912,7 +951,7 @@
|
||||
});
|
||||
ElMessage.success("导入成功");
|
||||
importConfigData.visible = false;
|
||||
mainStore.basePeers = [...new Set([config.serverUrl, ...mainStore.basePeers])];
|
||||
mainStore.basePeers = uniq([config.serverUrl, ...mainStore.basePeers]);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
if (err !== "cancel") {
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
/gen/schemas
|
||||
/easytier/logs
|
||||
/easytier/logs
|
||||
/easytier/logs/*.*
|
||||
Generated
+1
-1
@@ -1176,7 +1176,7 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
||||
|
||||
[[package]]
|
||||
name = "easytier-game"
|
||||
version = "1.1.8"
|
||||
version = "1.1.9"
|
||||
dependencies = [
|
||||
"log",
|
||||
"planif",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "easytier-game"
|
||||
version = "1.1.8"
|
||||
version = "1.1.9"
|
||||
homepage = "https://github.com/EasyTier/EasyTier"
|
||||
repository = "https://github.com/EasyTier/EasytierGame"
|
||||
description = "A simple network initiator based on Easytier"
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
"tcp",
|
||||
"udp"
|
||||
], // 协议类型
|
||||
"serverUrl": "public.easytier.top:11010", // easytier服务地址
|
||||
|
||||
// easytier服务地址 - 可填写多个 方式1,逗号分隔,"xxxx.cn,yyyy.com" 方式2,数组 ["xxxx.cn","yyyy.com"] (默认选中第一个)
|
||||
"serverUrl": "public.easytier.top:11010",
|
||||
"networkName": "", // 网络名
|
||||
"networkPassword": "", // 网络密码
|
||||
"hostname": "configTest", // 主机名
|
||||
@@ -18,5 +20,7 @@
|
||||
"disbleP2p": false, // 禁用p2p, 强制中转
|
||||
"dhcp": false, // 动态分配IP
|
||||
"devName": false, // 是否启用自定义网卡名
|
||||
"devNameValue": "" // 网卡名(启用devName之后才生效)
|
||||
"devNameValue": "", // 网卡名(启用devName之后才生效)
|
||||
"enableNetCardMetric": false, // 自定义easytier每次生成的网卡跃点
|
||||
"netCardMetricValue": 1 // 网卡跃点数量(1-9999)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||
"productName": "easytier-game",
|
||||
"version": "1.1.8",
|
||||
"version": "1.1.9",
|
||||
"identifier": "com.tauri.easytier-game",
|
||||
|
||||
"build": {
|
||||
@@ -13,7 +13,7 @@
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "easytier-game 1.1.8",
|
||||
"title": "easytier-game 1.1.9",
|
||||
"minWidth": 340,
|
||||
"width": 340,
|
||||
"height": 305,
|
||||
|
||||
+44
-8
@@ -27,7 +27,9 @@ export default defineStore("main", {
|
||||
saveErrorLog: true, // 是否保存错误日志
|
||||
logLevel: "error", //日志等级
|
||||
devName: false, //自定义网卡名
|
||||
devNameValue: "" //自定义网卡名
|
||||
devNameValue: "", //自定义网卡名
|
||||
enableNetCardMetric: false, //启用网卡自定义跃点
|
||||
netCardMetricValue: 1 //自定义网卡跃点值
|
||||
},
|
||||
cidrEnable: false,
|
||||
basePeers: ["public.easytier.top:11010"],
|
||||
@@ -38,15 +40,49 @@ export default defineStore("main", {
|
||||
createConfigInEasytier: false, //在easytier目录生成config.json文件吗
|
||||
|
||||
winipBcPid: 0,
|
||||
winipBcStart: false,
|
||||
|
||||
winipBcStart: false
|
||||
};
|
||||
},
|
||||
persist: {
|
||||
// 除了这些,其他都要存下来
|
||||
omit: [
|
||||
"winipBcPid",
|
||||
"winipBcStart"
|
||||
]
|
||||
// 防止持久化保存 用户使用config.json输入的无用的字段
|
||||
pick: [
|
||||
"config.protocol",
|
||||
"config.serverUrl",
|
||||
"config.networkName",
|
||||
"config.networkPassword",
|
||||
"config.hostname",
|
||||
"config.ipv4",
|
||||
"config.proxyNetworks",
|
||||
"config.autoStart",
|
||||
"config.coonectAfterStart",
|
||||
"config.disableIpv6",
|
||||
"config.disbleListenner",
|
||||
"config.disableEncryption",
|
||||
"config.multiThread",
|
||||
"config.enablExitNode",
|
||||
"config.noTun",
|
||||
"config.latencyfirst",
|
||||
"config.useSmoltcp",
|
||||
"config.disableUdpHolePunching",
|
||||
"config.relayAllPeerrpc",
|
||||
"config.disbleP2p",
|
||||
"config.dhcp",
|
||||
"config.saveErrorLog",
|
||||
"config.logLevel",
|
||||
"config.devName",
|
||||
"config.devNameValue",
|
||||
"config.enableNetCardMetric",
|
||||
"config.netCardMetricValue",
|
||||
|
||||
"cidrEnable",
|
||||
"basePeers",
|
||||
"theme",
|
||||
"configStartEnable",
|
||||
"configPath",
|
||||
"winIpBcAutoStart",
|
||||
"createConfigInEasytier"
|
||||
],
|
||||
// // 除了这些,其他都要存下来
|
||||
// omit: ["winipBcPid", "winipBcStart"]
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user