Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e35e38b11f | ||
|
|
9c59ee2163 | ||
|
|
a1ad7d1de3 | ||
|
|
2b9278dd65 | ||
|
|
1743ee3a18 | ||
|
|
580dc71743 | ||
|
|
6b5ef26f17 | ||
|
|
9f2875cd13 | ||
|
|
8a064a9d40 | ||
|
|
2dccec3070 | ||
|
|
3f678992d6 | ||
|
|
3b5ccd9a1b | ||
|
|
1b18a3a7ca | ||
|
|
e201281c36 | ||
|
|
cbd81f92f4 | ||
|
|
f364754092 | ||
|
|
8b760e5e9b | ||
|
|
3b2bfbb0e6 | ||
|
|
2c8691e9ae | ||
|
|
e6a2d26671 | ||
|
|
fafff8090f | ||
|
|
b37016a49c | ||
|
|
6e8c1d4a15 | ||
|
|
92f5289576 | ||
|
|
c62b46850c | ||
|
|
3d160f9b90 | ||
|
|
79efb9bd51 | ||
|
|
ef3c85c6d3 | ||
|
|
e61fc45ad2 | ||
|
|
de53f682f0 | ||
|
|
3ddfa189e9 | ||
|
|
ddc588c792 | ||
|
|
984afbdf0b | ||
|
|
56a72ad940 | ||
|
|
b62c539bdd | ||
|
|
d9272acb44 | ||
|
|
5c89eb5a58 | ||
|
|
583041c295 | ||
|
|
ded10d175f | ||
|
|
380682d175 | ||
|
|
055bddc22c | ||
|
|
5b2442591f | ||
|
|
3eb1a08697 | ||
|
|
79283f4039 | ||
|
|
497b828f2d | ||
|
|
41dc3e8fc4 | ||
|
|
eb1be4cdb8 | ||
|
|
d4655c1e50 | ||
|
|
b1debe0aab | ||
|
|
f5780a4366 | ||
|
|
101e3c5ffc | ||
|
|
97b3a57ee1 | ||
|
|
0788a32158 | ||
|
|
f553ddddd8 | ||
|
|
07fb477c3a | ||
|
|
f8b920100d | ||
|
|
cfdca6f031 | ||
|
|
085669e43a | ||
|
|
eda70a2aae | ||
|
|
c2be92c41b | ||
|
|
4bcd23389d | ||
|
|
2a51fcb47d | ||
|
|
2c2f05c5b2 | ||
|
|
ab92469f11 | ||
|
|
749f324f7d | ||
|
|
1c49c41b71 | ||
|
|
1993d3d295 | ||
|
|
dce7e54675 | ||
|
|
41c644f2af | ||
|
|
78be273c7a | ||
|
|
c94a7683e4 | ||
|
|
b407012bef | ||
|
|
bb7d28153f | ||
|
|
627d9c7cd2 | ||
|
|
53a83fd7a7 | ||
|
|
c2ca091662 | ||
|
|
738a755353 | ||
|
|
dcbd946407 | ||
|
|
2a8cebcbb5 | ||
|
|
434ec7b2df | ||
|
|
c2ff37facf | ||
|
|
f48c9b4d0b | ||
|
|
1d734479d1 | ||
|
|
a989581d59 | ||
|
|
6ab9d3842c | ||
|
|
b69b2941b6 | ||
|
|
90deaa84b4 | ||
|
|
403cc3fe52 | ||
|
|
dd4eb36c17 | ||
|
|
2645e16bee | ||
|
|
82668c4c6a | ||
|
|
8fce4a8995 | ||
|
|
4cfbebcc5a | ||
|
|
40db4236ba | ||
|
|
eef4687ed6 | ||
|
|
e9a3f4014e | ||
|
|
749aae02ca | ||
|
|
fc3fd10081 | ||
|
|
65e664f35f | ||
|
|
ab9a617619 | ||
|
|
f629bc9993 | ||
|
|
dc7f48139e | ||
|
|
da8c511d60 | ||
|
|
eb60f402a4 | ||
|
|
c82ce1ea35 | ||
|
|
9524ea5ab4 | ||
|
|
caf18eaa7a | ||
|
|
2cdcb4a599 | ||
|
|
3407ca61fd | ||
|
|
964b7ced8b | ||
|
|
702267003b | ||
|
|
abf970b783 | ||
|
|
6855b6299f | ||
|
|
b77d242bd9 | ||
|
|
01016b1fa1 | ||
|
|
b2b656b6cb | ||
|
|
aabe6664b4 | ||
|
|
5869a72645 | ||
|
|
df3ab12165 | ||
|
|
03fe8909d0 | ||
|
|
2ec4bc9333 | ||
|
|
c1b89a2b9a | ||
|
|
6706525e77 | ||
|
|
981b8377d8 | ||
|
|
945329d109 | ||
|
|
304f3484e3 | ||
|
|
47ad6dae6a | ||
|
|
0448bb0ea9 | ||
|
|
5009d148a1 | ||
|
|
8427103a7e | ||
|
|
2767cb44d7 | ||
|
|
416ffd6435 | ||
|
|
ff554ce369 | ||
|
|
0698671c05 | ||
|
|
67468cf28b | ||
|
|
058a6b7ab2 | ||
|
|
1ccb3656c2 | ||
|
|
6da7e1d4d0 | ||
|
|
119c8c87ee | ||
|
|
2758b4d896 | ||
|
|
d8c7f0ad56 | ||
|
|
0d8b51f199 | ||
|
|
6e296edf11 | ||
|
|
072066ac87 | ||
|
|
a359dea603 | ||
|
|
29decd4899 | ||
|
|
92a5d53d35 | ||
|
|
40e33dcb1c | ||
|
|
2b2757ccff | ||
|
|
f57f4097ac | ||
|
|
5865441074 | ||
|
|
2d916392c1 | ||
|
|
dec3b2261f | ||
|
|
5b0cb912e4 | ||
|
|
5cbdaa7134 | ||
|
|
b2f59431a6 | ||
|
|
04ec214714 | ||
|
|
196b56ab71 | ||
|
|
226742776f | ||
|
|
f4ec2ee5fa | ||
|
|
f33d37cd90 | ||
|
|
2394ec7f5d | ||
|
|
8baa61b72c | ||
|
|
f35ea79475 | ||
|
|
46b8ca0b63 | ||
|
|
b8cfaf308d | ||
|
|
c7d3e5021c | ||
|
|
a689b425ca | ||
|
|
9bd45157a4 | ||
|
|
169b8997ec | ||
|
|
aa6ea882d9 | ||
|
|
c86b275096 | ||
|
|
a81985549e | ||
|
|
f4e9409afa | ||
|
|
6647e5bd37 | ||
|
|
64b7c25de5 | ||
|
|
7c562228c6 | ||
|
|
91a194c948 | ||
|
|
50a30331e5 | ||
|
|
da47941564 | ||
|
|
6e999f92a0 | ||
|
|
f4fc0ef3c5 | ||
|
|
2dc8dc734b | ||
|
|
98663240de | ||
|
|
ba782c85d4 | ||
|
|
dea067b21f | ||
|
|
d56c73e2a3 | ||
|
|
5d208d1220 | ||
|
|
47a3a1c7ab | ||
|
|
56059b4f4f | ||
|
|
09577d5403 | ||
|
|
fb77f9432a | ||
|
|
0f70405041 | ||
|
|
399888f976 | ||
|
|
a8a0a14713 | ||
|
|
59af1e468d | ||
|
|
0d1bad5551 | ||
|
|
7eb2ff1624 | ||
|
|
72351ba60f | ||
|
|
7dc2dcc9db | ||
|
|
5b4a7d784d | ||
|
|
1d8d199af7 | ||
|
|
c4e29dc000 | ||
|
|
72ec031f8a | ||
|
|
2300b8d5db | ||
|
|
7ec81ab146 | ||
|
|
cf3ffeb8c6 | ||
|
|
118a7fe0f1 | ||
|
|
005c68cc5b | ||
|
|
70f390c5d7 | ||
|
|
65de82a227 | ||
|
|
a2494b59f7 | ||
|
|
b05269712a | ||
|
|
740463f017 | ||
|
|
30521d068e | ||
|
|
c7898401ce | ||
|
|
d169de9a9e | ||
|
|
74ddb428ee | ||
|
|
ba4837f1f8 | ||
|
|
cdf25f6b6f | ||
|
|
e630c53c9f | ||
|
|
db13f82bfc | ||
|
|
63ebaa5df8 | ||
|
|
7b886ea251 | ||
|
|
436c4d809c | ||
|
|
6ab7bac20b | ||
|
|
7f852ffb8e | ||
|
|
69e68810ba | ||
|
|
a63f79230b | ||
|
|
3b01c62ed2 | ||
|
|
cdc69d23b9 | ||
|
|
92a15afabf | ||
|
|
277e265bf1 | ||
|
|
473163e7c6 | ||
|
|
f1eb40bb0d | ||
|
|
6c23915615 | ||
|
|
d0361c29aa | ||
|
|
9ee1239341 | ||
|
|
a2a74980bf | ||
|
|
01c7f7d528 | ||
|
|
a9c8a667ec | ||
|
|
bcfb23a8fb | ||
|
|
111a98a916 | ||
|
|
784163d816 | ||
|
|
ce2a6533f2 | ||
|
|
17275e194a | ||
|
|
9664c9f11d | ||
|
|
8b1e4a3d1a | ||
|
|
e7347a1a26 | ||
|
|
a4cf38dd71 | ||
|
|
c018b23913 | ||
|
|
0c003616cb | ||
|
|
7bfd6517a7 | ||
|
|
42e5c94601 | ||
|
|
cd25afe0c7 | ||
|
|
302e4e327d | ||
|
|
52317d8d5a | ||
|
|
757bb2dd95 | ||
|
|
3be6550593 | ||
|
|
f79764dbb5 | ||
|
|
61a598d7e3 | ||
|
|
dc61940e3c | ||
|
|
086c4da557 | ||
|
|
d79b50527e | ||
|
|
4a91e5a6bd | ||
|
|
8db5fd1efd | ||
|
|
d22ba331d9 | ||
|
|
cc20e81ebf |
@@ -0,0 +1,32 @@
|
|||||||
|
name: Build project
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- Source/**
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- Source/**
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup MSBuild.exe
|
||||||
|
uses: microsoft/[email protected]
|
||||||
|
|
||||||
|
- name: Build release
|
||||||
|
run: msbuild Source/GrasscutterTools.sln /p:Configuration=Release /t:build /restore
|
||||||
|
|
||||||
|
- name: Upload build artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: GrasscutterTools
|
||||||
|
path: Source/GrasscutterTools/bin/Release/GrasscutterTools.exe
|
||||||
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 3.6 MiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 821 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 3.6 MiB |
@@ -3,26 +3,19 @@
|
|||||||
[](https://github.com/jie65535/GrasscutterCommandGenerator/blob/main/LICENSE)
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/blob/main/LICENSE)
|
||||||
[](https://github.com/jie65535/GrasscutterCommandGenerator/stargazers)
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/stargazers)
|
||||||
[](https://github.com/jie65535/GrasscutterCommandGenerator/releases)
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/releases)
|
||||||
[](https://qm.qq.com/cgi-bin/qm/qr?k=PdS9--b-n8LEAmYjX8fNFXtKDcsp4NHN&jump_from=webapi&authKey=7ty3ZCKYMKLGWLmO8O84qiNAZ0EuCnSGF+acP+74xuDMKYXXNjuPP7iUzffHz4r2)
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/releases/latest)
|
||||||
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/actions/workflows/build.yml)
|
||||||
|
[](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=fBizzp6RwJsIY7gFlmd4L-WG0V3aF8X3&authKey=mTjf%2B7jCIZess1HTRi05e5yi%2FHKA1auMwE8%2FJ960PFWk8WMATST654gWPi4OTHTZ&noverify=0&group_code=835489603)
|
||||||
|
|
||||||
English | [简体中文](README_zh-cn.md) | [Русский](README_ru-RU.md)
|
English | [简体中文](README_zh-cn.md) | [繁體中文](README_zh-tw.md) | [Русский](README_ru-RU.md)
|
||||||
|
|
||||||
## Commands Generator
|
## Commands Generator
|
||||||
|
|
||||||
Please download the latest version from [Releases](https://github.com/jie65535/GrasscutterCommandGenerator/releases)
|
Please download the latest committed automated build from [Action](https://github.com/jie65535/GrasscutterCommandGenerator/actions/workflows/build.yml), or a release from [Releases](https://github.com/jie65535/GrasscutterCommandGenerator/releases) (may be behind)
|
||||||
|
|
||||||
Support 简体中文, 繁体中文, English and Русский languages.
|
Support 简体中文, 繁體中文, English and Русский languages.
|
||||||
|
|
||||||
Welcome everyone to improve the [ID Resource](/Source/GrasscutterTools/Resources/en-us).
|
> **Warning**: app look may be different rather than on screenshots. It may also contain translation errors and a lack of certain resources. **We're welcome everyone to contribute to their [improvement](/Source/GrasscutterTools/Resources/en-us)**
|
||||||
|
|
||||||
## Update log
|
|
||||||
### GrasscutterTools-v1.7.0
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Remote command
|
## Remote command
|
||||||
|
|
||||||
@@ -39,6 +32,61 @@ The server require [gc-opencommand-plugin](https://github.com/jie65535/gc-openco
|
|||||||
>
|
>
|
||||||
> If you are not using port `80`, specify the port number to access in the url: http://127.0.0.1:443
|
> If you are not using port `80`, specify the port number to access in the url: http://127.0.0.1:443
|
||||||
|
|
||||||
|
## Update log
|
||||||
|
|
||||||
|
### GrasscutterTools-v1.13
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.11
|
||||||
|

|
||||||
|
|
||||||
|
Commandline Usages:
|
||||||
|
```bash
|
||||||
|
GcTools.exe -help
|
||||||
|
GcTools.exe -version
|
||||||
|
GcTools.exe -c "cmd arg"
|
||||||
|
GcTools.exe -c "cmd1 arg" && GcTools -c "cmd2 arg1 arg2"
|
||||||
|
GcTools.exe -host http://127.0.0.1:443 -token 123456 -c "cmd1 arg1 arg2 | cmd2 | cmd3 arg"
|
||||||
|
```
|
||||||
|
|
||||||
|
### GrasscutterTools-v1.10
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.9
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.8
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.3
|
||||||
|

|
||||||
|
|
||||||
|
Added [AttackModifier](https://github.com/NotThorny/AttackModifier), [AttackInfusedWithItem](https://github.com/snoobi-seggs/AttackInfusedWithItem), [SwitchElementTraveller](https://github.com/Penelopeep/SwitchElementTraveller) plugins command generation
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.2
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.1
|
||||||
|
- Gadgets(CHS Only)
|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.0
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,25 +3,18 @@
|
|||||||
[](https://github.com/jie65535/GrasscutterCommandGenerator/blob/main/LICENSE)
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/blob/main/LICENSE)
|
||||||
[](https://github.com/jie65535/GrasscutterCommandGenerator/stargazers)
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/stargazers)
|
||||||
[](https://github.com/jie65535/GrasscutterCommandGenerator/releases)
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/releases)
|
||||||
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/releases/latest)
|
||||||
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/actions/workflows/build.yml)
|
||||||
|
|
||||||
[English](README.md) | [简体中文](README_zh-cn.md) | Русский - Перевод [Юрий Дворецкий](https://github.com/yurikenjx) (с исправлениями от [EgorBron](https://github.com/EgorBron))
|
[English](README.md) | [简体中文](README_zh-cn.md) | [繁體中文](README_zh-tw.md) | Русский - Перевод [Юрий Дворецкий](https://github.com/yurikenjx) (с исправлениями от [EgorBron](https://github.com/EgorBron))
|
||||||
|
|
||||||
## Генератор команд (GCG)
|
## Генератор команд (GCG)
|
||||||
|
|
||||||
Загрузите последнюю версию из вкладки [Releases](https://github.com/jie65535/GrasscutterCommandGenerator/releases).
|
Пожалуйста, загрузите последнюю подтвержденную автоматизированную сборку из [Action](https://github.com/jie65535/GrasscutterCommandGenerator/actions/workflows/build.yml) или выпуск из [Releases](https://github.com/jie65535/GrasscutterCommandGenerator/releases) (может отставать)
|
||||||
|
|
||||||
GCG поддерживает 简体中文 (китайский упр.), 繁体中文 (китайский трад.), English (английский) и Русский языки.
|
GCG поддерживает 简体中文 (китайский упр.), 繁體中文 (китайский трад.), English (английский) и Русский языки.
|
||||||
|
|
||||||
Приглашаем всех улучшить [ID ресурсов и перевод](/Source/GrasscutterTools/Resources/ru-ru)
|
> **Warning**: вид приложения может отличаться от скриншотов. Также в нём могут присутствовать ошибки в переводе и отсутсвие некоторых ресурсов. **Мы приглашаем всех сделать вклад в их [улучшение](/Source/GrasscutterTools/Resources/ru-ru)**
|
||||||
|
|
||||||
## Update log
|
|
||||||
### GrasscutterTools-v1.7.0
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Удаленная команда (OpenCommand)
|
## Удаленная команда (OpenCommand)
|
||||||
|
|
||||||
@@ -39,38 +32,96 @@ GCG поддерживает 简体中文 (китайский упр.), 繁体
|
|||||||
>
|
>
|
||||||
> Если вы не указали порт `80` в конфиге, вам нужно указать свой порт в URL-адресе (например, http://127.0.0.1:443)
|
> Если вы не указали порт `80` в конфиге, вам нужно указать свой порт в URL-адресе (например, http://127.0.0.1:443)
|
||||||
|
|
||||||
|
|
||||||
|
## Лог обновлений
|
||||||
|
|
||||||
|
### GrasscutterTools-v1.13
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.11
|
||||||
|

|
||||||
|
|
||||||
|
Commandline Usages:
|
||||||
|
```bash
|
||||||
|
GcTools.exe -help
|
||||||
|
GcTools.exe -version
|
||||||
|
GcTools.exe -c "cmd arg"
|
||||||
|
GcTools.exe -c "cmd1 arg" && GcTools -c "cmd2 arg1 arg2"
|
||||||
|
GcTools.exe -host http://127.0.0.1:443 -token 123456 -c "cmd1 arg1 arg2 | cmd2 | cmd3 arg"
|
||||||
|
```
|
||||||
|
|
||||||
|
### GrasscutterTools-v1.10
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.9
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.8
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.3
|
||||||
|

|
||||||
|
|
||||||
|
Добавлена поддержка генерации команд для плагинов [AttackModifier](https://github.com/NotThorny/AttackModifier), [AttackInfusedWithItem](https://github.com/snoobi-seggs/AttackInfusedWithItem), [SwitchElementTraveller](https://github.com/Penelopeep/SwitchElementTraveller).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.2
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.1
|
||||||
|
- Гаджеты (пока что только на китайском)
|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.0
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Скриншоты
|
## Скриншоты
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|

|
||||||
@@ -3,31 +3,19 @@
|
|||||||
[](https://github.com/jie65535/GrasscutterCommandGenerator/blob/main/LICENSE)
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/blob/main/LICENSE)
|
||||||
[](https://github.com/jie65535/GrasscutterCommandGenerator/stargazers)
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/stargazers)
|
||||||
[](https://github.com/jie65535/GrasscutterCommandGenerator/releases)
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/releases)
|
||||||
[](https://qm.qq.com/cgi-bin/qm/qr?k=PdS9--b-n8LEAmYjX8fNFXtKDcsp4NHN&jump_from=webapi&authKey=7ty3ZCKYMKLGWLmO8O84qiNAZ0EuCnSGF+acP+74xuDMKYXXNjuPP7iUzffHz4r2)
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/releases/latest)
|
||||||
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/actions/workflows/build.yml)
|
||||||
|
[](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=fBizzp6RwJsIY7gFlmd4L-WG0V3aF8X3&authKey=mTjf%2B7jCIZess1HTRi05e5yi%2FHKA1auMwE8%2FJ960PFWk8WMATST654gWPi4OTHTZ&noverify=0&group_code=835489603)
|
||||||
|
|
||||||
[English](README.md) | 简体中文 | [Русский](README_ru-RU.md)
|
[English](README.md) | 简体中文 | [繁體中文](README_zh-tw.md) | [Русский](README_ru-RU.md)
|
||||||
|
|
||||||
## Commands Generator
|
## Commands Generator
|
||||||
|
|
||||||
请从 [Releases](https://github.com/jie65535/GrasscutterCommandGenerator/releases) 中获取最新版本
|
请从 [Action](https://github.com/jie65535/GrasscutterCommandGenerator/actions/workflows/build.yml) 中下载最新提交的自动构建版本,或者从 [Releases](https://github.com/jie65535/GrasscutterCommandGenerator/releases) 中下载发布版本(可能落后)
|
||||||
|
|
||||||
本工具支持 简体中文, 繁体中文, English 与 Русский 语言。
|
本工具支持 简体中文, 繁體中文, English 与 Русский 语言。
|
||||||
|
|
||||||
欢迎大家一起来完善工具的[内置资源](/Source/GrasscutterTools/Resources/zh-cn)。
|
> **Warning**: 应用程序的外观可能与截图上的不同。它也可能包含翻译错误和缺乏某些资源。**我们欢迎各位为此工具做出贡献并<a href="./Source/GrasscutterTools/Resources/zh-cn">改进</a> : )**
|
||||||
|
|
||||||
## Update log
|
|
||||||
|
|
||||||
### GrasscutterTools-v1.7.1
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### GrasscutterTools-v1.7.0
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 远程执行
|
## 远程执行
|
||||||
|
|
||||||
@@ -44,6 +32,66 @@
|
|||||||
>
|
>
|
||||||
> 如果使用的不是`80`端口,则要在url中指定访问的端口号:http://127.0.0.1:443
|
> 如果使用的不是`80`端口,则要在url中指定访问的端口号:http://127.0.0.1:443
|
||||||
|
|
||||||
|
|
||||||
|
## 更新概要
|
||||||
|
|
||||||
|
### GrasscutterTools-v1.13
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.11
|
||||||
|

|
||||||
|
|
||||||
|
命令行用法:
|
||||||
|
```bash
|
||||||
|
GcTools.exe -help
|
||||||
|
GcTools.exe -version
|
||||||
|
GcTools.exe -c "cmd arg"
|
||||||
|
GcTools.exe -c "cmd1 arg" && GcTools -c "cmd2 arg1 arg2"
|
||||||
|
GcTools.exe -host http://127.0.0.1:443 -token 123456 -c "cmd1 arg1 arg2 | cmd2 | cmd3 arg"
|
||||||
|
```
|
||||||
|
|
||||||
|
### GrasscutterTools-v1.10
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.9
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.8
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.3
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
新增[攻击修改](https://github.com/NotThorny/AttackModifier)、[攻击注入](https://github.com/snoobi-seggs/AttackInfusedWithItem)、[切换元素](https://github.com/Penelopeep/SwitchElementTraveller)等插件命令生成
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.2
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.1
|
||||||
|
- 增加了 Gadgets
|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.0
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 软件截图
|
## 软件截图
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
# Grasscutter Tools
|
||||||
|
|
||||||
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/blob/main/LICENSE)
|
||||||
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/stargazers)
|
||||||
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/releases)
|
||||||
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/releases/latest)
|
||||||
|
[](https://github.com/jie65535/GrasscutterCommandGenerator/actions/workflows/build.yml)
|
||||||
|
[](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=fBizzp6RwJsIY7gFlmd4L-WG0V3aF8X3&authKey=mTjf%2B7jCIZess1HTRi05e5yi%2FHKA1auMwE8%2FJ960PFWk8WMATST654gWPi4OTHTZ&noverify=0&group_code=835489603)
|
||||||
|
|
||||||
|
[English](README.md) | [简体中文](README_zh-cn.md) | 繁體中文 | [Русский](README_ru-RU.md)
|
||||||
|
|
||||||
|
## 指令產生工具
|
||||||
|
|
||||||
|
請從 [Action](https://github.com/jie65535/GrasscutterCommandGenerator/actions/workflows/build.yml) 中下載最新提交的自動構建版本,或者從 [Releases](https://github.com/jie65535/GrasscutterCommandGenerator/releases) 中下載發布版本(可能落後)
|
||||||
|
|
||||||
|
本工具支援 简体中文、繁體中文、English 及 Русский 上述語言。
|
||||||
|
|
||||||
|
> **Warning**: 程式中的實際外觀可能會與截圖中的內容不同。其中也可能包含翻譯錯誤及缺乏特定資源。**我們歡迎各位為此工具做出貢獻並[改進](/Source/GrasscutterTools/Resources/zh-tw)**
|
||||||
|
|
||||||
|
## 遠端控制
|
||||||
|
|
||||||
|
伺服器需要安裝 [gc-opencommand-plugin](https://github.com/jie65535/gc-opencommand-plugin) 插件
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
> 如果你無法連接至伺服器,請確認輸入的伺服器位址是否正確。
|
||||||
|
>
|
||||||
|
> 建議將伺服器調整為HTTP模式,如下圖所示(config.json):
|
||||||
|
> 
|
||||||
|
>
|
||||||
|
> 你可藉由任何瀏覽器輸入網址 http://127.0.0.1/status/server 以測試伺服器是否正常運作。
|
||||||
|
>
|
||||||
|
> 如果你並非使用`80`端口, 則須在網址後輸入指定端口: http://127.0.0.1:443
|
||||||
|
|
||||||
|
## 更新日誌
|
||||||
|
|
||||||
|
### GrasscutterTools-v1.13
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.11
|
||||||
|

|
||||||
|
|
||||||
|
Commandline Usages:
|
||||||
|
```bash
|
||||||
|
GcTools.exe -help
|
||||||
|
GcTools.exe -version
|
||||||
|
GcTools.exe -c "cmd arg"
|
||||||
|
GcTools.exe -c "cmd1 arg" && GcTools -c "cmd2 arg1 arg2"
|
||||||
|
GcTools.exe -host http://127.0.0.1:443 -token 123456 -c "cmd1 arg1 arg2 | cmd2 | cmd3 arg"
|
||||||
|
```
|
||||||
|
|
||||||
|
### GrasscutterTools-v1.10
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.9
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.8
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.3
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
新增 [攻擊修改](https://github.com/NotThorny/AttackModifier)、[攻擊注入](https://github.com/snoobi-seggs/AttackInfusedWithItem)、[主角切換元素](https://github.com/Penelopeep/SwitchElementTraveller)等插件指令產生
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.2
|
||||||
|

|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.1
|
||||||
|
- 新增 Gadgets
|
||||||
|
|
||||||
|
### GrasscutterTools-v1.7.0
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## 工具截圖
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
@@ -29,7 +29,7 @@
|
|||||||
<value>10001</value>
|
<value>10001</value>
|
||||||
</setting>
|
</setting>
|
||||||
<setting name="Host" serializeAs="String">
|
<setting name="Host" serializeAs="String">
|
||||||
<value>https://127.0.0.1</value>
|
<value>http://127.0.0.1:443</value>
|
||||||
</setting>
|
</setting>
|
||||||
<setting name="CheckedLastVersion" serializeAs="String">
|
<setting name="CheckedLastVersion" serializeAs="String">
|
||||||
<value />
|
<value />
|
||||||
@@ -49,6 +49,42 @@
|
|||||||
<setting name="DefaultMailSender" serializeAs="String">
|
<setting name="DefaultMailSender" serializeAs="String">
|
||||||
<value>GrasscutterTools</value>
|
<value>GrasscutterTools</value>
|
||||||
</setting>
|
</setting>
|
||||||
|
<setting name="ShopJsonPath" serializeAs="String">
|
||||||
|
<value />
|
||||||
|
</setting>
|
||||||
|
<setting name="MainFormLocation" serializeAs="String">
|
||||||
|
<value>0, 0</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="MainFormSize" serializeAs="String">
|
||||||
|
<value>0, 0</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="BannersJsonPath" serializeAs="String">
|
||||||
|
<value />
|
||||||
|
</setting>
|
||||||
|
<setting name="IsIncludeUID" serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="NavContainerSplitterDistance" serializeAs="String">
|
||||||
|
<value>0</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="ActivityConfigJsonPath" serializeAs="String">
|
||||||
|
<value />
|
||||||
|
</setting>
|
||||||
|
<setting name="ProjectResourcePath" serializeAs="String">
|
||||||
|
<value />
|
||||||
|
</setting>
|
||||||
|
<setting name="IsUpgraded" serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="IsHotkeyEenabled" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="AutoStartProxy" serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="WindowOpacity" serializeAs="String">
|
||||||
|
<value>100</value>
|
||||||
|
</setting>
|
||||||
</GrasscutterTools.Properties.Settings>
|
</GrasscutterTools.Properties.Settings>
|
||||||
</userSettings>
|
</userSettings>
|
||||||
</configuration>
|
</configuration>
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
|
|
||||||
namespace GrasscutterTools.Controls
|
|
||||||
{
|
|
||||||
[ToolboxItem(true)]
|
|
||||||
public class TextBoxXP : TextBox
|
|
||||||
{
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获得当前进程,以便重绘控件
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hWnd"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
private static extern IntPtr GetWindowDC(IntPtr hWnd);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
|
|
||||||
|
|
||||||
private const int EM_SETCUEBANNER = 0x1501;
|
|
||||||
|
|
||||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
|
||||||
private static extern Int32 SendMessage
|
|
||||||
(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 水印文本
|
|
||||||
/// </summary>
|
|
||||||
private string _Watermark = "";
|
|
||||||
|
|
||||||
private float maximum;
|
|
||||||
private float minimum;
|
|
||||||
|
|
||||||
#region 属性
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否启用热点效果
|
|
||||||
/// </summary>
|
|
||||||
[Category("外观")]
|
|
||||||
[Browsable(true)]
|
|
||||||
[Localizable(true)]
|
|
||||||
[Description("获取或设置输入框水印文本")]
|
|
||||||
[DefaultValue("")]
|
|
||||||
public string Watermark
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return this._Watermark;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
this._Watermark = value;
|
|
||||||
SendMessage(Handle, EM_SETCUEBANNER, 0, _Watermark);
|
|
||||||
this.Invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否只能输入数字
|
|
||||||
/// </summary>
|
|
||||||
[Category("行为")]
|
|
||||||
[Browsable(true)]
|
|
||||||
[Description("获取或设置TextBox是否只允许输入数字")]
|
|
||||||
[DefaultValue(false)]
|
|
||||||
public bool DigitOnly { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 转为数值
|
|
||||||
/// </summary>
|
|
||||||
public float Number
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (float.TryParse(Text, out float value))
|
|
||||||
return value;
|
|
||||||
else
|
|
||||||
return 0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Category("数据")]
|
|
||||||
[Browsable(true)]
|
|
||||||
[DefaultValue(0)]
|
|
||||||
[Description("指示小数点后位数")]
|
|
||||||
public int DecimalPlaces { get; set; }
|
|
||||||
|
|
||||||
[Category("数据")]
|
|
||||||
[Description("获取或设置限制的最大值")]
|
|
||||||
public float Maximum
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return maximum;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
maximum = value;
|
|
||||||
if (minimum > maximum)
|
|
||||||
{
|
|
||||||
minimum = maximum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Category("数据")]
|
|
||||||
[Browsable(true)]
|
|
||||||
[Description("获取或设置限制的最小值")]
|
|
||||||
public float Minimum
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return minimum;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
minimum = value;
|
|
||||||
if (minimum > maximum)
|
|
||||||
{
|
|
||||||
maximum = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion 属性
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public TextBoxXP()
|
|
||||||
: base()
|
|
||||||
{
|
|
||||||
//BorderStyle = BorderStyle.FixedSingle;
|
|
||||||
//Font = Styles.StaticResources.DefaultFont;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnKeyPress(KeyPressEventArgs e)
|
|
||||||
{
|
|
||||||
base.OnKeyPress(e);
|
|
||||||
// 如果只允许输入数字,则判断输入是否为退格或者数字
|
|
||||||
if (DigitOnly)
|
|
||||||
{
|
|
||||||
//IsNumber:指定字符串中位于指定位置的字符是否属于数字类别
|
|
||||||
//IsPunctuation:指定字符串中位于指定位置的字符是否属于标点符号类别
|
|
||||||
//IsControl:指定字符串中位于指定位置的字符是否属于控制字符类别
|
|
||||||
if (!Char.IsNumber(e.KeyChar) && !Char.IsPunctuation(e.KeyChar) && !Char.IsControl(e.KeyChar))
|
|
||||||
{
|
|
||||||
e.Handled = true; //获取或设置一个值,指示是否处理过System.Windows.Forms.Control.KeyPress事件
|
|
||||||
}
|
|
||||||
else if (Char.IsPunctuation(e.KeyChar) && DecimalPlaces > 0)
|
|
||||||
{
|
|
||||||
if (e.KeyChar == '.')
|
|
||||||
{
|
|
||||||
if (Text.LastIndexOf('.') != -1)
|
|
||||||
{
|
|
||||||
e.Handled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
e.Handled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnLeave(EventArgs e)
|
|
||||||
{
|
|
||||||
base.OnLeave(e);
|
|
||||||
|
|
||||||
if (DigitOnly)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(Text))
|
|
||||||
{
|
|
||||||
if (Number > Maximum)
|
|
||||||
Text = Maximum.ToString("F" + DecimalPlaces);
|
|
||||||
if (Number < Minimum)
|
|
||||||
Text = Minimum.ToString("F" + DecimalPlaces);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,8 +14,9 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using GrasscutterTools.DispatchServer.Model;
|
using GrasscutterTools.DispatchServer.Model;
|
||||||
@@ -23,7 +24,7 @@ using GrasscutterTools.Utils;
|
|||||||
|
|
||||||
namespace GrasscutterTools.DispatchServer
|
namespace GrasscutterTools.DispatchServer
|
||||||
{
|
{
|
||||||
public static class DispatchServerAPI
|
internal static class DispatchServerAPI
|
||||||
{
|
{
|
||||||
public static async Task<ServerStatus> QueryServerStatus(string host)
|
public static async Task<ServerStatus> QueryServerStatus(string host)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,13 +14,14 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
**/
|
**/
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace GrasscutterTools.DispatchServer.Model
|
namespace GrasscutterTools.DispatchServer.Model
|
||||||
{
|
{
|
||||||
public class ServerStatus
|
internal class ServerStatus
|
||||||
{
|
{
|
||||||
[JsonProperty("playerCount")]
|
[JsonProperty("playerCount")]
|
||||||
public int PlayerCount { get; set; }
|
public int PlayerCount { get; set; }
|
||||||
@@ -32,7 +33,7 @@ namespace GrasscutterTools.DispatchServer.Model
|
|||||||
public string Version { get; set; }
|
public string Version { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ServerStatusResponse
|
internal class ServerStatusResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("retcode")]
|
[JsonProperty("retcode")]
|
||||||
public int RetCode { get; set; }
|
public int RetCode { get; set; }
|
||||||
|
|||||||
@@ -0,0 +1,202 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
|
||||||
|
namespace Eavesdrop;
|
||||||
|
|
||||||
|
public sealed class Certifier : IDisposable
|
||||||
|
{
|
||||||
|
private readonly X509Store _rootStore, _myStore;
|
||||||
|
private readonly IDictionary<string, X509Certificate2> _certificateCache;
|
||||||
|
|
||||||
|
public string Issuer { get; }
|
||||||
|
public string CertificateAuthorityName { get; }
|
||||||
|
|
||||||
|
public DateTime NotAfter { get; set; }
|
||||||
|
public DateTime NotBefore { get; set; }
|
||||||
|
public int KeyLength { get; set; } = 1024;
|
||||||
|
public bool IsCachingSignedCertificates { get; set; }
|
||||||
|
|
||||||
|
public X509Certificate2? Authority { get; private set; }
|
||||||
|
|
||||||
|
public Certifier()
|
||||||
|
: this("Eavesdrop")
|
||||||
|
{ }
|
||||||
|
public Certifier(string issuer)
|
||||||
|
: this(issuer, $"{issuer} Root Certificate Authority", StoreLocation.CurrentUser)
|
||||||
|
{ }
|
||||||
|
public Certifier(string issuer, string certificateAuthorityName)
|
||||||
|
: this(issuer, certificateAuthorityName, StoreLocation.CurrentUser)
|
||||||
|
{ }
|
||||||
|
public Certifier(string issuer, string certificateAuthorityName, StoreLocation location)
|
||||||
|
{
|
||||||
|
_myStore = new X509Store(StoreName.My, location);
|
||||||
|
_rootStore = new X509Store(StoreName.Root, location);
|
||||||
|
_certificateCache = new Dictionary<string, X509Certificate2>();
|
||||||
|
|
||||||
|
NotBefore = DateTime.Now;
|
||||||
|
NotAfter = NotBefore.AddMonths(1);
|
||||||
|
|
||||||
|
Issuer = issuer;
|
||||||
|
CertificateAuthorityName = certificateAuthorityName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CreateTrustedRootCertificate()
|
||||||
|
{
|
||||||
|
return (Authority = InstallCertificate(_rootStore, CertificateAuthorityName)) != null;
|
||||||
|
}
|
||||||
|
public bool DestroyTrustedRootCertificate()
|
||||||
|
{
|
||||||
|
return DestroyCertificates(_rootStore);
|
||||||
|
}
|
||||||
|
public bool ExportTrustedRootCertificate(string path)
|
||||||
|
{
|
||||||
|
X509Certificate2? rootCertificate = InstallCertificate(_rootStore, CertificateAuthorityName);
|
||||||
|
|
||||||
|
path = Path.GetFullPath(path);
|
||||||
|
if (rootCertificate != null)
|
||||||
|
{
|
||||||
|
byte[] data = rootCertificate.Export(X509ContentType.Cert);
|
||||||
|
File.WriteAllBytes(path, data);
|
||||||
|
}
|
||||||
|
return File.Exists(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public X509Certificate2? GenerateCertificate(string certificateName)
|
||||||
|
{
|
||||||
|
return InstallCertificate(_myStore, certificateName);
|
||||||
|
}
|
||||||
|
public X509Certificate2 CreateCertificate(string subjectName, string alternateName)
|
||||||
|
{
|
||||||
|
using var rsa = RSA.Create(KeyLength);
|
||||||
|
var certificateRequest = new CertificateRequest(subjectName, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
|
||||||
|
if (Authority == null)
|
||||||
|
{
|
||||||
|
certificateRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(true, false, 0, true));
|
||||||
|
certificateRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(certificateRequest.PublicKey, false));
|
||||||
|
|
||||||
|
using X509Certificate2 certificate = certificateRequest.CreateSelfSigned(NotBefore.ToUniversalTime(), NotAfter.ToUniversalTime());
|
||||||
|
|
||||||
|
certificate.FriendlyName = alternateName;
|
||||||
|
return new X509Certificate2(certificate.Export(X509ContentType.Pfx, string.Empty), string.Empty, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var sanBuilder = new SubjectAlternativeNameBuilder();
|
||||||
|
sanBuilder.AddDnsName(alternateName);
|
||||||
|
|
||||||
|
certificateRequest.CertificateExtensions.Add(sanBuilder.Build());
|
||||||
|
certificateRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(false, false, 0, false));
|
||||||
|
certificateRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(certificateRequest.PublicKey, false));
|
||||||
|
|
||||||
|
using X509Certificate2 certificate = certificateRequest.Create(Authority, Authority.NotBefore, Authority.NotAfter, Guid.NewGuid().ToByteArray());
|
||||||
|
using X509Certificate2 certificateWithPrivateKey = certificate.CopyWithPrivateKey(rsa);
|
||||||
|
|
||||||
|
certificateWithPrivateKey.FriendlyName = alternateName;
|
||||||
|
return new X509Certificate2(certificateWithPrivateKey.Export(X509ContentType.Pfx, string.Empty), string.Empty, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private X509Certificate2? InstallCertificate(X509Store store, string certificateName)
|
||||||
|
{
|
||||||
|
if (_certificateCache.TryGetValue(certificateName, out X509Certificate2? certificate))
|
||||||
|
{
|
||||||
|
if (DateTime.Now >= certificate.NotAfter)
|
||||||
|
{
|
||||||
|
_certificateCache.Remove(certificateName);
|
||||||
|
}
|
||||||
|
else return certificate;
|
||||||
|
}
|
||||||
|
lock (store)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
store.Open(OpenFlags.ReadWrite);
|
||||||
|
string subjectName = $"CN={certificateName}, O={Issuer}";
|
||||||
|
|
||||||
|
certificate = FindCertificates(store, subjectName)?[0];
|
||||||
|
if (certificate != null && DateTime.Now >= certificate.NotAfter)
|
||||||
|
{
|
||||||
|
if (Authority == null)
|
||||||
|
{
|
||||||
|
DestroyCertificates();
|
||||||
|
store.Open(OpenFlags.ReadWrite);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
store.Remove(certificate);
|
||||||
|
}
|
||||||
|
certificate = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (certificate == null)
|
||||||
|
{
|
||||||
|
certificate = CreateCertificate(subjectName, certificateName);
|
||||||
|
if (certificate != null)
|
||||||
|
{
|
||||||
|
if (store == _rootStore || IsCachingSignedCertificates)
|
||||||
|
{
|
||||||
|
store.Add(certificate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return certificate;
|
||||||
|
}
|
||||||
|
catch { return certificate = null; }
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
store.Close();
|
||||||
|
if (certificate != null && !_certificateCache.ContainsKey(certificateName))
|
||||||
|
{
|
||||||
|
_certificateCache.Add(certificateName, certificate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DestroyCertificates(X509Store store)
|
||||||
|
{
|
||||||
|
lock (store)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
store.Open(OpenFlags.ReadWrite);
|
||||||
|
X509Certificate2Collection certificates = store.Certificates.Find(X509FindType.FindByIssuerName, Issuer, false);
|
||||||
|
|
||||||
|
store.RemoveRange(certificates);
|
||||||
|
IEnumerable<string> subjectNames = certificates.Cast<X509Certificate2>().Select(c => c.GetNameInfo(X509NameType.SimpleName, false));
|
||||||
|
|
||||||
|
foreach (string subjectName in subjectNames)
|
||||||
|
{
|
||||||
|
if (!_certificateCache.ContainsKey(subjectName)) continue;
|
||||||
|
_certificateCache.Remove(subjectName);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch { return false; }
|
||||||
|
finally { store.Close(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public bool DestroyCertificates() => DestroyCertificates(_myStore) && DestroyCertificates(_rootStore);
|
||||||
|
|
||||||
|
private static X509Certificate2Collection? FindCertificates(X509Store store, string subjectName)
|
||||||
|
{
|
||||||
|
X509Certificate2Collection certificates = store.Certificates
|
||||||
|
.Find(X509FindType.FindBySubjectDistinguishedName, subjectName, false);
|
||||||
|
|
||||||
|
return certificates.Count > 0 ? certificates : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_myStore.Close();
|
||||||
|
_rootStore.Close();
|
||||||
|
|
||||||
|
_myStore.Dispose();
|
||||||
|
_rootStore.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||