mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
Compare commits
590 Commits
TEngine3.0
...
TEngine6.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
eaccfdad5b | ||
![]() |
b6fbdf1d22 | ||
![]() |
e2de2ba994 | ||
![]() |
3b68cb1519 | ||
![]() |
be12d1024a | ||
![]() |
55ffdf4edb | ||
![]() |
511619cb71 | ||
![]() |
5b8793de40 | ||
![]() |
9c9079c55b | ||
![]() |
c8482799c5 | ||
![]() |
cb86d8868e | ||
![]() |
f2c7ff4336 | ||
![]() |
c18cdacdbb | ||
![]() |
b18298cbd9 | ||
![]() |
86b1ff5d7b | ||
![]() |
71eb698038 | ||
![]() |
57c08d4e92 | ||
![]() |
45f5bf3dc7 | ||
![]() |
7a86b80c2b | ||
![]() |
07fb31cc1c | ||
![]() |
4a1f2b52f6 | ||
![]() |
aee8a4a3dc | ||
![]() |
7621ba4b4a | ||
![]() |
53e16dc1ff | ||
![]() |
e26a2937a7 | ||
![]() |
e7344db57d | ||
![]() |
8ab792b778 | ||
![]() |
d6917f28b7 | ||
![]() |
9aef4d4081 | ||
![]() |
7d1de6e9a3 | ||
![]() |
9e0e762a39 | ||
![]() |
ad2bde9259 | ||
![]() |
cb8f15ad88 | ||
![]() |
b4639fcbdc | ||
![]() |
cc9002fe9a | ||
![]() |
e64926a66a | ||
![]() |
32c1edd0a5 | ||
![]() |
c6f1508e84 | ||
![]() |
1f129118a7 | ||
![]() |
6dac7b44a6 | ||
![]() |
2e8d181bed | ||
![]() |
b42daa035e | ||
![]() |
e7b07dfea2 | ||
![]() |
62c05e7c2b | ||
![]() |
4c4a882b21 | ||
![]() |
58d7847079 | ||
![]() |
724f52bbab | ||
![]() |
0b409436a0 | ||
![]() |
cc799ce426 | ||
![]() |
35a9729930 | ||
![]() |
0e34c99398 | ||
![]() |
240da47fc3 | ||
![]() |
04109a43b6 | ||
![]() |
bc82685ec7 | ||
![]() |
1894cd4d72 | ||
![]() |
4c903e8da5 | ||
![]() |
03aabf6b08 | ||
![]() |
c1d9fe5ca7 | ||
![]() |
122b5b27ad | ||
![]() |
9a8de43e95 | ||
![]() |
06d826d4b2 | ||
![]() |
afd0c6a24e | ||
![]() |
7f9dddaec0 | ||
![]() |
d97538481e | ||
![]() |
c72ef8e197 | ||
![]() |
7c9393051c | ||
![]() |
e4c3247546 | ||
![]() |
6e9d23b2dc | ||
![]() |
eae827a600 | ||
![]() |
f916adb71b | ||
![]() |
227283864f | ||
![]() |
32418326b1 | ||
![]() |
6570f87074 | ||
![]() |
81b00ae913 | ||
![]() |
322aaa0a46 | ||
![]() |
8f5b1b2117 | ||
![]() |
54a4c55f3c | ||
![]() |
e37c066f9f | ||
![]() |
b1d06ecef5 | ||
![]() |
27ce7e8ecc | ||
![]() |
8b715ffc8e | ||
![]() |
e8fa910f1f | ||
![]() |
3b3bc7822a | ||
![]() |
3c662e489e | ||
![]() |
5cebc82ba1 | ||
![]() |
5cb72e0b08 | ||
![]() |
500e012f2e | ||
![]() |
82332ba5b4 | ||
![]() |
55a6ab1ffb | ||
![]() |
24313b61ab | ||
![]() |
876b36b3b9 | ||
![]() |
2a62a1f320 | ||
![]() |
b6e6c1c423 | ||
![]() |
230f6a0be5 | ||
![]() |
25ca5f3f2b | ||
![]() |
66c5a41be5 | ||
![]() |
61ba472346 | ||
![]() |
9ce4fb9d88 | ||
![]() |
e405236d4d | ||
![]() |
2e27941755 | ||
![]() |
14bbb993f8 | ||
![]() |
0ba9d1a8b7 | ||
![]() |
2818edb575 | ||
![]() |
5210c1d36b | ||
![]() |
cdc7a8f688 | ||
![]() |
c20f8285d8 | ||
![]() |
f2a63978da | ||
![]() |
36db2f3aba | ||
![]() |
61b2baeaf7 | ||
![]() |
7aab91215c | ||
![]() |
4ae417337b | ||
![]() |
52ac77d5e4 | ||
![]() |
515d55e19a | ||
![]() |
a4221e36f8 | ||
![]() |
58cecd2071 | ||
![]() |
81a794cff3 | ||
![]() |
5e6d98764c | ||
![]() |
385de69cb9 | ||
![]() |
b68a5a84b9 | ||
![]() |
8ede4c7faa | ||
![]() |
f4d89bb420 | ||
![]() |
202df9ff62 | ||
![]() |
e4989425e8 | ||
![]() |
a7b6d6f478 | ||
![]() |
db3fd11cb2 | ||
![]() |
a2fe29af24 | ||
![]() |
bf92b4d568 | ||
![]() |
b060057c36 | ||
![]() |
9bffcce30e | ||
![]() |
be3b6eb8f2 | ||
![]() |
a61d8bd668 | ||
![]() |
fae2afd3c8 | ||
![]() |
a309cd2f98 | ||
![]() |
3dc478c509 | ||
![]() |
c728dc4c0f | ||
![]() |
e9d6c27006 | ||
![]() |
33bdcbd913 | ||
![]() |
ac236e4b6a | ||
![]() |
d6f5e65ab4 | ||
![]() |
95412017e3 | ||
![]() |
07f02acb1e | ||
![]() |
c03170e860 | ||
![]() |
aa5dc9dcb4 | ||
![]() |
53665f669c | ||
![]() |
91403615bc | ||
![]() |
77b2fdceb8 | ||
![]() |
7b7b14a8c3 | ||
![]() |
c7f3511bd3 | ||
![]() |
e089aead36 | ||
![]() |
d169b62fc5 | ||
![]() |
ab10c587f8 | ||
![]() |
bbeecb2855 | ||
![]() |
39c9d327a1 | ||
![]() |
50c72fb341 | ||
![]() |
b0c357bba2 | ||
![]() |
6a1ea3d9b8 | ||
![]() |
6a6caebcff | ||
![]() |
e3bf57f485 | ||
![]() |
77d07e175a | ||
![]() |
106d90da4d | ||
![]() |
dd471eed08 | ||
![]() |
f32e5e79a3 | ||
![]() |
4c325f7ca6 | ||
![]() |
d11b6e628e | ||
![]() |
5e568b203b | ||
![]() |
5bb168a958 | ||
![]() |
6cf5aa46c1 | ||
![]() |
9b72cbcb7c | ||
![]() |
32fbb971e7 | ||
![]() |
d6d2f66902 | ||
![]() |
4a1876897c | ||
![]() |
551727687f | ||
![]() |
aad8ff3ee5 | ||
![]() |
df25a1adad | ||
![]() |
634a392a1f | ||
![]() |
b869a05220 | ||
![]() |
37d88c2d94 | ||
![]() |
f3aa8824d8 | ||
![]() |
99c5afcbc5 | ||
![]() |
4075588c34 | ||
![]() |
fdd9f34132 | ||
![]() |
a2ab6efc71 | ||
![]() |
67025c806e | ||
![]() |
38afa45f9c | ||
![]() |
0dc572f43e | ||
![]() |
0679d924c1 | ||
![]() |
3de8cad99a | ||
![]() |
065d5a7303 | ||
![]() |
c089eb32ba | ||
![]() |
d571a937f8 | ||
![]() |
89210483a9 | ||
![]() |
058ac2c9a5 | ||
![]() |
990222c7c6 | ||
![]() |
d3914a96bb | ||
![]() |
4b178a9fa9 | ||
![]() |
79929c4ac3 | ||
![]() |
38fa4d5cbc | ||
![]() |
3ac6977f93 | ||
![]() |
3facec8f93 | ||
![]() |
0570982b97 | ||
![]() |
f785264873 | ||
![]() |
4911ec074c | ||
![]() |
6ff9546152 | ||
![]() |
5a8dc04b9c | ||
![]() |
d4482cf1c4 | ||
![]() |
c7fad139ba | ||
![]() |
650469a7db | ||
![]() |
c7c00eac9f | ||
![]() |
5a883bc8ec | ||
![]() |
79c1026c7c | ||
![]() |
f2c69d58b2 | ||
![]() |
c38d3b7cfa | ||
![]() |
98cb74537a | ||
![]() |
ed19a75be9 | ||
![]() |
fd82ddf427 | ||
![]() |
e53ceb0095 | ||
![]() |
9afda78735 | ||
![]() |
5734d4f995 | ||
![]() |
dc7ab7fd64 | ||
![]() |
fcb3416acd | ||
![]() |
3df18c006d | ||
![]() |
6cfae215dc | ||
![]() |
1aaa46c82c | ||
![]() |
ca79adce7c | ||
![]() |
b520eba187 | ||
![]() |
b5afaca217 | ||
![]() |
ea2efbf588 | ||
![]() |
a4b1befc5a | ||
![]() |
8dcddfa328 | ||
![]() |
dd37d130da | ||
![]() |
24d7dbc677 | ||
![]() |
491100b932 | ||
![]() |
c84c21574d | ||
![]() |
7914660f8c | ||
![]() |
b00679a276 | ||
![]() |
cd9a10ccac | ||
![]() |
f11098d32e | ||
![]() |
db6e715fa6 | ||
![]() |
c2edf71ee4 | ||
![]() |
75af7c22c7 | ||
![]() |
2f9edf83bf | ||
![]() |
815095efaf | ||
![]() |
3101a64a48 | ||
![]() |
457e0f36a4 | ||
![]() |
0bd30def23 | ||
![]() |
d24db83c8b | ||
![]() |
18a2840777 | ||
![]() |
1d901514e1 | ||
![]() |
983279c56d | ||
![]() |
e9540c620a | ||
![]() |
39be280d88 | ||
![]() |
f9f9122027 | ||
![]() |
682a0bd786 | ||
![]() |
34c514cae8 | ||
![]() |
c707cc1a38 | ||
![]() |
f016fdd0a6 | ||
![]() |
4c0f5a77f9 | ||
![]() |
ae0d00424f | ||
![]() |
c8ecac5815 | ||
![]() |
4f8c1cdfdd | ||
![]() |
dff043e075 | ||
![]() |
e69dc47b8f | ||
![]() |
fc2ef0714c | ||
![]() |
d75c1c8c93 | ||
![]() |
83bea559e4 | ||
![]() |
26689639ed | ||
![]() |
bd6ac5f4da | ||
![]() |
70dcb03a3f | ||
![]() |
59b3649155 | ||
![]() |
2c025efe3b | ||
![]() |
7ae6ef94ba | ||
![]() |
d5bb64b314 | ||
![]() |
4c34858ce0 | ||
![]() |
5adb2f83e5 | ||
![]() |
f10a89180e | ||
![]() |
3e3314858e | ||
![]() |
da57ed845f | ||
![]() |
df570f453a | ||
![]() |
a500a08a30 | ||
![]() |
2daac0e065 | ||
![]() |
514da6e99e | ||
![]() |
7f91241df7 | ||
![]() |
071974ab4f | ||
![]() |
c01e03ff70 | ||
![]() |
6fec792e05 | ||
![]() |
04ecf71eab | ||
![]() |
693ca5bb3d | ||
![]() |
90f84a2764 | ||
![]() |
6107b41770 | ||
![]() |
1423a3716a | ||
![]() |
6a87db76ee | ||
![]() |
3a6170dca6 | ||
![]() |
9d137d613a | ||
![]() |
ba77ec6b45 | ||
![]() |
b661da68f2 | ||
![]() |
e1040110bb | ||
![]() |
2d53fa1687 | ||
![]() |
c4ef07f13e | ||
![]() |
1f2d99ddc9 | ||
![]() |
edf4925a7a | ||
![]() |
5d67238c8f | ||
![]() |
6cfd352482 | ||
![]() |
40373c473d | ||
![]() |
d799f9fdf0 | ||
![]() |
15735c3d2d | ||
![]() |
818a74f437 | ||
![]() |
f248757401 | ||
![]() |
6ada0e7de7 | ||
![]() |
7ea472f97e | ||
![]() |
fb8528ff52 | ||
![]() |
e3ac92ef46 | ||
![]() |
be6a19c26a | ||
![]() |
e7f0636f30 | ||
![]() |
fb38e96e9e | ||
![]() |
dd658c7e1d | ||
![]() |
4d7cb7641d | ||
![]() |
ae075b1fad | ||
![]() |
02827ce3b8 | ||
![]() |
1a0e3f91e0 | ||
![]() |
6d376b0e07 | ||
![]() |
cb73c9a9eb | ||
![]() |
7dda73a7ac | ||
![]() |
9bcb636ed7 | ||
![]() |
bd0cfc5577 | ||
![]() |
ff613e4130 | ||
![]() |
fea1ae2278 | ||
![]() |
866c440479 | ||
![]() |
48ff839d64 | ||
![]() |
69be3cfa23 | ||
![]() |
5f2c27ecf0 | ||
![]() |
ef17cd851b | ||
![]() |
f186d6b058 | ||
![]() |
4385123976 | ||
![]() |
1334dc30f9 | ||
![]() |
af822add2c | ||
![]() |
ffb1f214ad | ||
![]() |
213aaed426 | ||
![]() |
623d301e41 | ||
![]() |
2870383afe | ||
![]() |
1ad435958a | ||
![]() |
386787c6ec | ||
![]() |
cd65dde4c3 | ||
![]() |
8321e77421 | ||
![]() |
1b6f80952e | ||
![]() |
b52e655c30 | ||
![]() |
8c0df95626 | ||
![]() |
0d1e308f1c | ||
![]() |
f8797538fd | ||
![]() |
fe4e168041 | ||
![]() |
8e9047d3a3 | ||
![]() |
04bfaeccc8 | ||
![]() |
d66c823c15 | ||
![]() |
0ec1424f0a | ||
![]() |
01f8eb9d57 | ||
![]() |
f5021a9688 | ||
![]() |
a632f7a5ad | ||
![]() |
5f968f4154 | ||
![]() |
c9fe83c2bd | ||
![]() |
2c00d103cb | ||
![]() |
1d56437d9f | ||
![]() |
69db1ff977 | ||
![]() |
48887b1aee | ||
![]() |
381ea8bb8d | ||
![]() |
7401edac15 | ||
![]() |
b1c7f30be9 | ||
![]() |
cfaf82a623 | ||
![]() |
6992d12c6c | ||
![]() |
119d9683ad | ||
![]() |
9478868513 | ||
![]() |
6ed32082e1 | ||
![]() |
6ee515e8c5 | ||
![]() |
b839afa76a | ||
![]() |
d9605b348a | ||
![]() |
dfef83919c | ||
![]() |
f5f983f220 | ||
![]() |
d61b1206ee | ||
![]() |
3650ba1a8b | ||
![]() |
8f14a4d2cb | ||
![]() |
dc22e595c9 | ||
![]() |
0e70f7d446 | ||
![]() |
039569b2d4 | ||
![]() |
ea38004ba2 | ||
![]() |
cc97c0583a | ||
![]() |
887094a4b1 | ||
![]() |
0d09a7e73b | ||
![]() |
d8f8514f9d | ||
![]() |
f2f6b2422f | ||
![]() |
3a9cad9397 | ||
![]() |
5e70e7972e | ||
![]() |
8d2b4200d6 | ||
![]() |
b983e85416 | ||
![]() |
99d2afdbd7 | ||
![]() |
57ce836b3c | ||
![]() |
8dce78d6fb | ||
![]() |
6d41adffd9 | ||
![]() |
cb9129261b | ||
![]() |
89dd6214d4 | ||
![]() |
1aec76d64c | ||
![]() |
859f654f6d | ||
![]() |
391d690f9d | ||
![]() |
bb0b4104f9 | ||
![]() |
20d0ecd8da | ||
![]() |
8c3d6308b9 | ||
![]() |
4c8c37ffd8 | ||
![]() |
5f694c2bed | ||
![]() |
7ff74bb747 | ||
![]() |
a5de63397a | ||
![]() |
13cc62f3f1 | ||
![]() |
95dfac5294 | ||
![]() |
14e95107c9 | ||
![]() |
caf5b2b54e | ||
![]() |
285483034e | ||
![]() |
1cdd8b63b4 | ||
![]() |
4c748df7ac | ||
![]() |
e1229b5a4b | ||
![]() |
b937fb1a37 | ||
![]() |
87ab99b363 | ||
![]() |
e3a47393f4 | ||
![]() |
75725314ad | ||
![]() |
d3ed2b21b9 | ||
![]() |
ec34dfbb16 | ||
![]() |
bd76e3a651 | ||
![]() |
278c8f23be | ||
![]() |
42568db2ab | ||
![]() |
b033c59b00 | ||
![]() |
04a43a3f11 | ||
![]() |
54214cdd0b | ||
![]() |
fa870b6228 | ||
![]() |
8a49d3437b | ||
![]() |
f19b889deb | ||
![]() |
d55f6e29d9 | ||
![]() |
8e4af31f26 | ||
![]() |
58a4b3e043 | ||
![]() |
576bf3bb48 | ||
![]() |
d282b81546 | ||
![]() |
d6dcd8851c | ||
![]() |
bbea9c4cee | ||
![]() |
b1ccb1fd53 | ||
![]() |
0f2ad3c71d | ||
![]() |
0e6851e691 | ||
![]() |
75b9956261 | ||
![]() |
401c397fc8 | ||
![]() |
94b314e91f | ||
![]() |
a6573d9336 | ||
![]() |
abf5357f49 | ||
![]() |
aab353cca3 | ||
![]() |
e13071c4db | ||
![]() |
e071c20214 | ||
![]() |
bf73ce333b | ||
![]() |
d7a60002d4 | ||
![]() |
61f657322d | ||
![]() |
33223dc02e | ||
![]() |
0661c59877 | ||
![]() |
7c74e10857 | ||
![]() |
db935bfb5f | ||
![]() |
dc6b7bb21e | ||
![]() |
d32f3cb768 | ||
![]() |
a32ab30444 | ||
![]() |
aa0d40c758 | ||
![]() |
5239b89326 | ||
![]() |
53f0ecb6c1 | ||
![]() |
ea9447d0ea | ||
![]() |
0c6d59f53e | ||
![]() |
9986e22d18 | ||
![]() |
7deb049769 | ||
![]() |
fce8bd4d60 | ||
![]() |
7ec14c670f | ||
![]() |
efe3d2b25b | ||
![]() |
2107282368 | ||
![]() |
fb26ea2297 | ||
![]() |
9ac150425f | ||
![]() |
36d2c146b0 | ||
![]() |
774b73bbbf | ||
![]() |
32366eb127 | ||
![]() |
a843617e5f | ||
![]() |
46b139f7cf | ||
![]() |
e6ff1dec3f | ||
![]() |
4429732010 | ||
![]() |
60a5caebae | ||
![]() |
f7c95d8216 | ||
![]() |
98dcb80942 | ||
![]() |
30192d52cf | ||
![]() |
b7b2262d53 | ||
![]() |
d1c93f15d6 | ||
![]() |
1ac1ff7d56 | ||
![]() |
863788f303 | ||
![]() |
74790c7486 | ||
![]() |
1c223c8ad0 | ||
![]() |
e75b3a4e66 | ||
![]() |
91b0995911 | ||
![]() |
14c886ea8f | ||
![]() |
9babc0ba85 | ||
![]() |
f8056aef32 | ||
![]() |
846dc4d4bc | ||
![]() |
03ab7fb353 | ||
![]() |
3c11980e7c | ||
![]() |
c23aa0bd71 | ||
![]() |
df76d0b77a | ||
![]() |
35d2012546 | ||
![]() |
c96d20a89a | ||
![]() |
5787d0f9dc | ||
![]() |
8b35c8ca07 | ||
![]() |
e5456da482 | ||
![]() |
144ba9f222 | ||
![]() |
889fbdc8e1 | ||
![]() |
0d177e6868 | ||
![]() |
29135228be | ||
![]() |
c1a1de73cd | ||
![]() |
612e9b7eba | ||
![]() |
5ed6b8c378 | ||
![]() |
06dad5a68a | ||
![]() |
9e0462043c | ||
![]() |
c1178e284b | ||
![]() |
8e3dd138a6 | ||
![]() |
405253c507 | ||
![]() |
66ef50a9e0 | ||
![]() |
413f4dcda7 | ||
![]() |
75fdb4d7de | ||
![]() |
1ada1e4e33 | ||
![]() |
3848b6aaaa | ||
![]() |
2b33b405c0 | ||
![]() |
6766b930d7 | ||
![]() |
526baf45fa | ||
![]() |
a473971cfb | ||
![]() |
51effd2c97 | ||
![]() |
4205220b64 | ||
![]() |
e95c18ca67 | ||
![]() |
f5571716a2 | ||
![]() |
d61a8dfa4b | ||
![]() |
068ec709d0 | ||
![]() |
8b26b790ee | ||
![]() |
da35b4306b | ||
![]() |
ee2147e3d9 | ||
![]() |
a273e9d5f8 | ||
![]() |
31d4d6c0b8 | ||
![]() |
6a6f0591f1 | ||
![]() |
9cd0bac81e | ||
![]() |
4abe10eecf | ||
![]() |
bd10297dfa | ||
![]() |
7ce72b8aa8 | ||
![]() |
c6ecb48944 | ||
![]() |
c178f8bb75 | ||
![]() |
d4f160d284 | ||
![]() |
d87653a9fb | ||
![]() |
04a5a0e048 | ||
![]() |
c825f4d920 | ||
![]() |
b3e59b92d6 | ||
![]() |
37af620d71 | ||
![]() |
493172a925 | ||
![]() |
1382db8c61 | ||
![]() |
72b7149aa1 | ||
![]() |
0c51ae7bdd | ||
![]() |
79dc302f14 | ||
![]() |
95e4dd93a8 | ||
![]() |
2b310c00f2 | ||
![]() |
fbb26ea9ea | ||
![]() |
bff8f20af3 | ||
![]() |
0c7ce5f28c | ||
![]() |
31fc9abdf9 | ||
![]() |
a087f40e8a | ||
![]() |
7b2fc7ce9f | ||
![]() |
dc4bb8cc9c | ||
![]() |
0c8f3a5f92 | ||
![]() |
a69f53592e | ||
![]() |
8757e1f550 | ||
![]() |
336d4b2eb9 | ||
![]() |
e0be062006 | ||
![]() |
5e69129667 | ||
![]() |
4c39ab79ca | ||
![]() |
a710d1cb76 | ||
![]() |
8472839394 | ||
![]() |
4988c99d31 | ||
![]() |
4fa62b2d79 | ||
![]() |
f549514d7c | ||
![]() |
f588038848 | ||
![]() |
9e0e3ebd50 | ||
![]() |
b07ef836a9 | ||
![]() |
7a1d593195 | ||
![]() |
bc113c5c6e | ||
![]() |
753bbdfb82 | ||
![]() |
6a6d33c536 | ||
![]() |
57a014a83a | ||
![]() |
9d1a8e8c9d | ||
![]() |
86c26cd21b | ||
![]() |
b60b9fff42 | ||
![]() |
990e17a6cc | ||
![]() |
be531bfad0 | ||
![]() |
6c46f3e5fd | ||
![]() |
e4b48e3c58 | ||
![]() |
68e5b1d482 |
122
.gitignore
vendored
122
.gitignore
vendored
@@ -1,119 +1,15 @@
|
||||
# This .gitignore file should be placed at the root of your Unity project directory
|
||||
#
|
||||
# Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore
|
||||
#
|
||||
/[Ll]ibrary/
|
||||
/[Tt]emp/
|
||||
/[Oo]bj/
|
||||
/[Bb]uild/
|
||||
/[Bb]uilds/
|
||||
/[Ll]ogs/
|
||||
/[Mm]emoryCaptures/
|
||||
/EditorBuild/
|
||||
# /[Aa]ssets/TResources/DLL/
|
||||
/[Aa]ssets/StreamingAssets
|
||||
/BuildBundleInfo/
|
||||
[Aa]ssets/AATest/
|
||||
[Aa]ssets/AATest.meta
|
||||
|
||||
# Asset meta data should only be ignored when the corresponding asset is also ignored
|
||||
!/[Aa]ssets/**/*.meta
|
||||
|
||||
# Uncomment this line if you wish to ignore the asset store tools plugin
|
||||
# /[Aa]ssets/AssetStoreTools*
|
||||
|
||||
# Autogenerated Jetbrains Rider plugin
|
||||
[Aa]ssets/Plugins/Editor/JetBrains*
|
||||
|
||||
# Visual Studio cache directory
|
||||
.vs/
|
||||
|
||||
# Gradle cache directory
|
||||
.gradle/
|
||||
|
||||
# Autogenerated VS/MD/Consulo solution and project files
|
||||
ExportedObj/
|
||||
.consulo/
|
||||
*.csproj
|
||||
*.unityproj
|
||||
*.sln
|
||||
*.suo
|
||||
*.tmp
|
||||
*.user
|
||||
*.userprefs
|
||||
*.pidb
|
||||
*.booproj
|
||||
*.svd
|
||||
*.pdb
|
||||
*.mdb
|
||||
*.opendb
|
||||
*.VC.db
|
||||
|
||||
# Unity3D generated meta files
|
||||
*.pidb.meta
|
||||
*.pdb.meta
|
||||
*.mdb.meta
|
||||
|
||||
# Unity3D generated file on crash reports
|
||||
sysinfo.txt
|
||||
|
||||
# Builds
|
||||
*.apk
|
||||
|
||||
# Crashlytics generated file
|
||||
crashlytics-build.properties
|
||||
|
||||
# TEnginePersistentDataPath
|
||||
TEnginePersistentDataPath/
|
||||
|
||||
# Hotfix
|
||||
TEngineHotUpdate/bin
|
||||
TEngineHotUpdate/obj
|
||||
|
||||
#HybirdCLR(HuaTuo)
|
||||
/HybirdCLRData/
|
||||
[Hh]ybridCLRData/
|
||||
|
||||
|
||||
#AATemp
|
||||
[Aa]ssets/AATemp/
|
||||
[Aa]ssets/AATemp.meta
|
||||
|
||||
#Rider
|
||||
/.idea/
|
||||
|
||||
# ABConfig
|
||||
[Aa]ssets/BuildConfig/
|
||||
[Aa]ssets/BuildConfig.meta
|
||||
|
||||
[Aa]ssets/StreamingAssets/
|
||||
[Aa]ssets/StreamingAssets.meta
|
||||
Assets/HybridCLRBuildCache/AssetBundleOutput.meta
|
||||
Assets/HybridCLRBuildCache/AssetBundleOutput/StandaloneWindows.meta
|
||||
Assets/HybridCLRBuildCache.meta
|
||||
Assets/HybridCLRBuildCache/AssetBundleSourceData.meta
|
||||
Assets/HybridCLRBuildCache/AssetBundleSourceData/StandaloneWindows.meta
|
||||
|
||||
#Bundles
|
||||
Bundles/
|
||||
|
||||
#Sandbox
|
||||
Sandbox/
|
||||
UnityProject/UserSettings/Layouts/default-2021.dwlt
|
||||
UnityProject/UserSettings/Search.settings
|
||||
|
||||
#Luban
|
||||
Luban/.cache.meta
|
||||
Tools/Luban/
|
||||
Tools/Luban.ClientServer/
|
||||
Configs/.cache.meta
|
||||
GenerateDatas/
|
||||
|
||||
#HybridCLR
|
||||
Assets/HybridCLRData.meta
|
||||
UserSettings/Search.settings
|
||||
#FileServer
|
||||
Tools/FileServer/AssetRoot
|
||||
|
||||
#Unity UserSettings
|
||||
UserSettings/Search.index
|
||||
UserSettings/Layouts/default-2021.dwlt
|
||||
|
||||
#UnityOnlineServiceData
|
||||
Assets/UnityOnlineServiceData.meta
|
||||
Assets/UnityOnlineServiceData
|
||||
|
||||
.DS_Store
|
||||
UnityProject/ProjectSettings/CommonBurstAotSettings.json
|
||||
UnityProject/ProjectSettings/BurstAotSettings_StandaloneWindows.json
|
||||
|
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad23fce0bd282924fa4aedb4da24684f
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
Before Width: | Height: | Size: 7.4 KiB |
@@ -1,96 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9a06e163014f4f46b14f4499d3e7240
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 0
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
Before Width: | Height: | Size: 7.2 KiB |
@@ -1,147 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2761fc23b4aa7e34187ac5ffbc3fad9b
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 268, y: 79, z: 267, w: 82}
|
||||
spriteGenerateFallbackPhysicsShape: 0
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
cookieLightType: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
Before Width: | Height: | Size: 2.9 KiB |
@@ -1,147 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d623a2b7e069a4c4592d3da48f476189
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 39, y: 38, z: 40, w: 37}
|
||||
spriteGenerateFallbackPhysicsShape: 0
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
cookieLightType: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
Before Width: | Height: | Size: 6.0 KiB |
@@ -1,147 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57e4117f4cd6ae54284898652e70d553
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 12
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 0
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
cookieLightType: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,69 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!687078895 &4343727234628468602
|
||||
SpriteAtlas:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UIRaw_Atlas_Common
|
||||
serializedVersion: 2
|
||||
m_EditorData:
|
||||
serializedVersion: 2
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
anisoLevel: 0
|
||||
compressionQuality: 0
|
||||
maxTextureSize: 0
|
||||
textureCompression: 0
|
||||
filterMode: 1
|
||||
generateMipMaps: 0
|
||||
readable: 0
|
||||
crunchedCompression: 0
|
||||
sRGB: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
m_BuildTarget: iPhone
|
||||
m_MaxTextureSize: 2048
|
||||
m_ResizeAlgorithm: 0
|
||||
m_TextureFormat: 49
|
||||
m_TextureCompression: 1
|
||||
m_CompressionQuality: 100
|
||||
m_CrunchedCompression: 0
|
||||
m_AllowsAlphaSplitting: 0
|
||||
m_Overridden: 1
|
||||
m_AndroidETC2FallbackOverride: 0
|
||||
m_ForceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
packingSettings:
|
||||
serializedVersion: 2
|
||||
padding: 2
|
||||
blockOffset: 1
|
||||
allowAlphaSplitting: 0
|
||||
enableRotation: 1
|
||||
enableTightPacking: 0
|
||||
enableAlphaDilation: 0
|
||||
secondaryTextureSettings: {}
|
||||
variantMultiplier: 1
|
||||
packables:
|
||||
- {fileID: 21300000, guid: f9a06e163014f4f46b14f4499d3e7240, type: 3}
|
||||
- {fileID: 21300000, guid: 2761fc23b4aa7e34187ac5ffbc3fad9b, type: 3}
|
||||
- {fileID: 21300000, guid: d623a2b7e069a4c4592d3da48f476189, type: 3}
|
||||
- {fileID: 21300000, guid: 57e4117f4cd6ae54284898652e70d553, type: 3}
|
||||
bindAsDefault: 1
|
||||
isAtlasV2: 0
|
||||
cachedData: {fileID: 0}
|
||||
m_MasterAtlas: {fileID: 0}
|
||||
m_PackedSprites:
|
||||
- {fileID: 21300000, guid: 2761fc23b4aa7e34187ac5ffbc3fad9b, type: 3}
|
||||
- {fileID: 21300000, guid: f9a06e163014f4f46b14f4499d3e7240, type: 3}
|
||||
- {fileID: 21300000, guid: d623a2b7e069a4c4592d3da48f476189, type: 3}
|
||||
- {fileID: 21300000, guid: 57e4117f4cd6ae54284898652e70d553, type: 3}
|
||||
m_PackedSpriteNamesToIndex:
|
||||
- red_button
|
||||
- blue_button
|
||||
- white_background
|
||||
- white_button
|
||||
m_RenderDataMap: {}
|
||||
m_Tag: UIRaw_Atlas_Common
|
||||
m_IsVariant: 0
|
||||
m_IsPlaceholder: 0
|
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a8431d2a64361c4d821790ed88aeb3d
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 4343727234628468602
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f69993ae3e14f924aa33b8747244c587
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22d1bcdd317c6f64daeb9bf9742495f2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,62 +0,0 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine.Editor.Inspector
|
||||
{
|
||||
[CustomEditor(typeof(Network))]
|
||||
internal sealed class NetworkInspector : GameFrameworkInspector
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
if (!EditorApplication.isPlaying)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Available during runtime only.", MessageType.Info);
|
||||
return;
|
||||
}
|
||||
|
||||
Network t = (Network)target;
|
||||
|
||||
if (IsPrefabInHierarchy(t.gameObject))
|
||||
{
|
||||
EditorGUILayout.LabelField("Network Channel Count", t.NetworkChannelCount.ToString());
|
||||
|
||||
INetworkChannel[] networkChannels = t.GetAllNetworkChannels();
|
||||
foreach (INetworkChannel networkChannel in networkChannels)
|
||||
{
|
||||
DrawNetworkChannel(networkChannel);
|
||||
}
|
||||
}
|
||||
|
||||
Repaint();
|
||||
}
|
||||
|
||||
private void DrawNetworkChannel(INetworkChannel networkChannel)
|
||||
{
|
||||
EditorGUILayout.BeginVertical("box");
|
||||
{
|
||||
EditorGUILayout.LabelField(networkChannel.Name, networkChannel.Connected ? "Connected" : "Disconnected");
|
||||
EditorGUILayout.LabelField("Service Type", networkChannel.ServiceType.ToString());
|
||||
EditorGUILayout.LabelField("Address Family", networkChannel.AddressFamily.ToString());
|
||||
EditorGUILayout.LabelField("Local Address", networkChannel.Connected ? networkChannel.Socket.LocalEndPoint.ToString() : "Unavailable");
|
||||
EditorGUILayout.LabelField("Remote Address", networkChannel.Connected ? networkChannel.Socket.RemoteEndPoint.ToString() : "Unavailable");
|
||||
EditorGUILayout.LabelField("Send Packet", Utility.Text.Format("{0} / {1}", networkChannel.SendPacketCount, networkChannel.SentPacketCount));
|
||||
EditorGUILayout.LabelField("Receive Packet", Utility.Text.Format("{0} / {1}", networkChannel.ReceivePacketCount, networkChannel.ReceivedPacketCount));
|
||||
EditorGUILayout.LabelField("Miss Heart Beat Count", networkChannel.MissHeartBeatCount.ToString());
|
||||
EditorGUILayout.LabelField("Heart Beat", Utility.Text.Format("{0:F2} / {1:F2}", networkChannel.HeartBeatElapseSeconds, networkChannel.HeartBeatInterval));
|
||||
EditorGUI.BeginDisabledGroup(!networkChannel.Connected);
|
||||
{
|
||||
if (GUILayout.Button("Disconnect"))
|
||||
{
|
||||
networkChannel.Close();
|
||||
}
|
||||
}
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
EditorGUILayout.Separator();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3301ba180cdc446bbdf823c860ae7a68
|
||||
timeCreated: 1682045195
|
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4944189ec9c939b45a65d93c704a22ec
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,489 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEditor.U2D;
|
||||
using UnityEngine;
|
||||
using UnityEngine.U2D;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
/// <summary>
|
||||
/// 图集导入管线。
|
||||
/// </summary>
|
||||
public class SpritePostprocessor : AssetPostprocessor
|
||||
{
|
||||
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
|
||||
{
|
||||
foreach (var s in importedAssets)
|
||||
{
|
||||
EditorSpriteSaveInfo.OnImportSprite(s);
|
||||
}
|
||||
|
||||
foreach (var s in deletedAssets)
|
||||
{
|
||||
EditorSpriteSaveInfo.OnDeleteSprite(s);
|
||||
}
|
||||
|
||||
foreach (var s in movedFromAssetPaths)
|
||||
{
|
||||
EditorSpriteSaveInfo.OnDeleteSprite(s);
|
||||
}
|
||||
|
||||
foreach (var s in movedAssets)
|
||||
{
|
||||
EditorSpriteSaveInfo.OnImportSprite(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class EditorSpriteSaveInfo
|
||||
{
|
||||
private const string NormalAtlasDir = "Assets/Atlas";
|
||||
private const string UISpritePath = "Assets/AssetRaw/UIRaw";
|
||||
private const string UIAtlasPath = "Assets/AssetRaw/UIRaw/Atlas";
|
||||
private const string UIRawPath = "Assets/AssetRaw/UIRaw/UIRaw";
|
||||
private static List<string> m_dirtyAtlasList = new List<string>();
|
||||
private static Dictionary<string, List<string>> m_allASprites = new Dictionary<string, List<string>>();
|
||||
private static Dictionary<string, string> m_uiAtlasMap = new Dictionary<string, string>();
|
||||
private static bool m_inited = false;
|
||||
private static bool m_dirty = false;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
if (m_inited)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EditorApplication.update += CheckDirty;
|
||||
}
|
||||
|
||||
public static void CheckDirty()
|
||||
{
|
||||
if (m_dirty)
|
||||
{
|
||||
m_dirty = false;
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
float lastProgress = -1;
|
||||
for (int i = 0; i < m_dirtyAtlasList.Count; i++)
|
||||
{
|
||||
string atlasName = m_dirtyAtlasList[i];
|
||||
Debug.Log("更新图集 : " + atlasName);
|
||||
var curProgress = (float)i / m_dirtyAtlasList.Count;
|
||||
if (curProgress > lastProgress + 0.01f)
|
||||
{
|
||||
lastProgress = curProgress;
|
||||
var progressText = $"当前进度:{i}/{m_dirtyAtlasList.Count} {atlasName}";
|
||||
bool cancel = EditorUtility.DisplayCancelableProgressBar("刷新图集" + atlasName, progressText, curProgress);
|
||||
if (cancel)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool isUI = atlasName.StartsWith("UIRaw");
|
||||
SaveAtlas(atlasName, isUI);
|
||||
}
|
||||
|
||||
EditorUtility.ClearProgressBar();
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
m_dirtyAtlasList.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnImportSprite(string assetPath)
|
||||
{
|
||||
if (!assetPath.StartsWith(UISpritePath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TextureImporter ti = AssetImporter.GetAtPath(assetPath) as TextureImporter;
|
||||
|
||||
if (ti != null)
|
||||
{
|
||||
var modify = false;
|
||||
|
||||
if (assetPath.StartsWith(UISpritePath))
|
||||
{
|
||||
if (ti.textureType != TextureImporterType.Sprite)
|
||||
{
|
||||
ti.textureType = TextureImporterType.Sprite;
|
||||
modify = true;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(ti.spritePackingTag))
|
||||
{
|
||||
ti.spritePackingTag = string.Empty;
|
||||
modify = true;
|
||||
}
|
||||
|
||||
var setting = new TextureImporterSettings();
|
||||
ti.ReadTextureSettings(setting);
|
||||
if (setting.spriteGenerateFallbackPhysicsShape)
|
||||
{
|
||||
setting.spriteGenerateFallbackPhysicsShape = false;
|
||||
ti.SetTextureSettings(setting);
|
||||
modify = true;
|
||||
}
|
||||
|
||||
if (IsKeepRawImage(assetPath))
|
||||
{
|
||||
//调整android格式
|
||||
var andPlatformSettings = ti.GetPlatformTextureSettings("Android");
|
||||
if (!andPlatformSettings.overridden)
|
||||
{
|
||||
andPlatformSettings.overridden = true;
|
||||
modify = true;
|
||||
}
|
||||
|
||||
if (andPlatformSettings.format != TextureImporterFormat.ASTC_6x6)
|
||||
{
|
||||
andPlatformSettings.format = TextureImporterFormat.ASTC_6x6;
|
||||
ti.SetPlatformTextureSettings(andPlatformSettings);
|
||||
modify = true;
|
||||
}
|
||||
|
||||
//调整ios格式
|
||||
var iosPlatformSettings = ti.GetPlatformTextureSettings("iPhone");
|
||||
if (!iosPlatformSettings.overridden)
|
||||
{
|
||||
iosPlatformSettings.overridden = true;
|
||||
modify = true;
|
||||
}
|
||||
|
||||
if (iosPlatformSettings.format != TextureImporterFormat.ASTC_5x5)
|
||||
{
|
||||
iosPlatformSettings.format = TextureImporterFormat.ASTC_5x5;
|
||||
iosPlatformSettings.compressionQuality = 50;
|
||||
ti.SetPlatformTextureSettings(iosPlatformSettings);
|
||||
modify = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (modify)
|
||||
{
|
||||
ti.SaveAndReimport();
|
||||
}
|
||||
|
||||
if (ti.textureType == TextureImporterType.Sprite)
|
||||
{
|
||||
OnProcessSprite(assetPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否保持散图(不打图集)
|
||||
/// </summary>
|
||||
/// <param name="dirPath"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsKeepRawImage(string dirPath)
|
||||
{
|
||||
return dirPath.Contains("UIRaw/Raw/") || dirPath.Contains("UIRaw_Raw_");
|
||||
}
|
||||
|
||||
public static string GetSpritePath(string assetPath)
|
||||
{
|
||||
string path = assetPath.Substring(0, assetPath.LastIndexOf("."));
|
||||
path = path.Replace("Assets/AssetRaw/", "");
|
||||
return path;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据文件路径,返回图集名称
|
||||
/// </summary>
|
||||
/// <param name="fullName"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetPackageTag(string fullName)
|
||||
{
|
||||
fullName = fullName.Replace("\\", "/");
|
||||
int idx = fullName.LastIndexOf("UIRaw", StringComparison.Ordinal);
|
||||
if (idx == -1)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
if (IsKeepRawImage(fullName))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
var atlasPath = fullName.Substring(idx);
|
||||
string str = atlasPath;
|
||||
str = str.Substring(0, str.LastIndexOf("/", StringComparison.Ordinal)).Replace("/", "_");
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
public static void OnProcessSprite(string assetPath)
|
||||
{
|
||||
if (!assetPath.StartsWith("Assets"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (assetPath.StartsWith("Assets/UIRaw_Delete"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Init();
|
||||
|
||||
var spriteName = Path.GetFileNameWithoutExtension(assetPath);
|
||||
var spritePath = GetSpritePath(assetPath);
|
||||
if (!m_uiAtlasMap.TryGetValue(spriteName, out string oldAssetPath) || spritePath == oldAssetPath)
|
||||
{
|
||||
m_uiAtlasMap[spriteName] = spritePath;
|
||||
m_dirty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"有重名的图片:{spriteName}\n旧图集:{oldAssetPath}\n新图集:{spritePath} ");
|
||||
m_uiAtlasMap[spriteName] = spritePath;
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
string atlasName = GetPackageTag(assetPath);
|
||||
if (string.IsNullOrEmpty(atlasName))
|
||||
{
|
||||
bool keepRaw = IsKeepRawImage(assetPath);
|
||||
if (!keepRaw)
|
||||
{
|
||||
Debug.LogError($"empty packingTag of asset :{assetPath} !!!");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
List<string> ret;
|
||||
if (!m_allASprites.TryGetValue(atlasName, out ret))
|
||||
{
|
||||
ret = new List<string>();
|
||||
m_allASprites.Add(atlasName, ret);
|
||||
}
|
||||
|
||||
if (!ret.Contains(assetPath))
|
||||
{
|
||||
ret.Add(assetPath);
|
||||
m_dirty = true;
|
||||
if (!m_dirtyAtlasList.Contains(atlasName))
|
||||
{
|
||||
m_dirtyAtlasList.Add(atlasName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnDeleteSprite(string assetPath)
|
||||
{
|
||||
if (assetPath.StartsWith("Assets/UIRaw_Delete"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!assetPath.StartsWith(UISpritePath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Init();
|
||||
string atlasName = GetPackageTag(assetPath);
|
||||
if (!m_allASprites.TryGetValue(atlasName, out var ret))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//改成文件名的匹配
|
||||
if (!ret.Exists(s => Path.GetFileName(s) == Path.GetFileName(assetPath)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (assetPath.StartsWith(UISpritePath))
|
||||
{
|
||||
var spriteName = Path.GetFileNameWithoutExtension(assetPath);
|
||||
if (m_uiAtlasMap.ContainsKey(spriteName))
|
||||
{
|
||||
m_uiAtlasMap.Remove(spriteName);
|
||||
m_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
ret.Remove(assetPath);
|
||||
m_dirty = true;
|
||||
if (!m_dirtyAtlasList.Contains(atlasName))
|
||||
{
|
||||
m_dirtyAtlasList.Add(atlasName);
|
||||
}
|
||||
}
|
||||
|
||||
#region 更新图集
|
||||
|
||||
public static void SaveAtlas(string atlasName, bool isUI)
|
||||
{
|
||||
List<Object> spriteList = new List<Object>();
|
||||
if (m_allASprites.ContainsKey(atlasName))
|
||||
{
|
||||
var list = m_allASprites[atlasName];
|
||||
list.Sort(StringComparer.Ordinal);
|
||||
|
||||
foreach (var s in list)
|
||||
{
|
||||
var sprite = AssetDatabase.LoadAssetAtPath<Sprite>(s);
|
||||
if (sprite != null)
|
||||
{
|
||||
spriteList.Add(sprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var path = $"{NormalAtlasDir}/{atlasName}.spriteatlas";
|
||||
|
||||
if (spriteList.Count == 0)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
{
|
||||
AssetDatabase.DeleteAsset(path);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var atlas = new SpriteAtlas();
|
||||
var setting = new SpriteAtlasPackingSettings
|
||||
{
|
||||
blockOffset = 1,
|
||||
padding = 2,
|
||||
enableRotation = true
|
||||
};
|
||||
|
||||
bool isOpaque = atlasName.Contains("Opaque");
|
||||
|
||||
var textureSetting = new SpriteAtlasTextureSettings
|
||||
{
|
||||
generateMipMaps = false,
|
||||
sRGB = true,
|
||||
filterMode = FilterMode.Bilinear
|
||||
};
|
||||
atlas.SetTextureSettings(textureSetting);
|
||||
|
||||
var iphonePlatformSetting = atlas.GetPlatformSettings("iPhone");
|
||||
if (!iphonePlatformSetting.overridden)
|
||||
{
|
||||
iphonePlatformSetting.overridden = true;
|
||||
iphonePlatformSetting.format = isOpaque ? TextureImporterFormat.ASTC_5x5 : TextureImporterFormat.ASTC_5x5;
|
||||
iphonePlatformSetting.compressionQuality = 100;
|
||||
atlas.SetPlatformSettings(iphonePlatformSetting);
|
||||
}
|
||||
|
||||
var androidPlatformSetting = atlas.GetPlatformSettings("Android");
|
||||
if (isOpaque && !androidPlatformSetting.overridden)
|
||||
{
|
||||
androidPlatformSetting.overridden = true;
|
||||
androidPlatformSetting.format = TextureImporterFormat.ETC_RGB4;
|
||||
androidPlatformSetting.compressionQuality = 100;
|
||||
atlas.SetPlatformSettings(androidPlatformSetting);
|
||||
}
|
||||
|
||||
atlas.SetPackingSettings(setting);
|
||||
atlas.Add(spriteList.ToArray());
|
||||
|
||||
AssetDatabase.CreateAsset(atlas, path);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 重新生成图集
|
||||
|
||||
private static Dictionary<string, List<string>> m_tempAllASprites = new Dictionary<string, List<string>>();
|
||||
|
||||
[MenuItem("TEngine/图集/重新生成UI图集")]
|
||||
static void ForceGenAtlas()
|
||||
{
|
||||
Init();
|
||||
List<string> needSaveAtlas = new List<string>();
|
||||
m_tempAllASprites.Clear();
|
||||
var findAssets = AssetDatabase.FindAssets("t:sprite", new[] { UIAtlasPath });
|
||||
foreach (var findAsset in findAssets)
|
||||
{
|
||||
var path = AssetDatabase.GUIDToAssetPath(findAsset);
|
||||
var atlasName = GetPackageTag(path);
|
||||
if (!m_tempAllASprites.TryGetValue(atlasName, out var spriteList))
|
||||
{
|
||||
spriteList = new List<string>();
|
||||
m_tempAllASprites[atlasName] = spriteList;
|
||||
}
|
||||
|
||||
if (!spriteList.Contains(path))
|
||||
{
|
||||
spriteList.Add(path);
|
||||
}
|
||||
}
|
||||
|
||||
//有变化的才刷
|
||||
var iter = m_tempAllASprites.GetEnumerator();
|
||||
while (iter.MoveNext())
|
||||
{
|
||||
bool needSave = false;
|
||||
var atlasName = iter.Current.Key;
|
||||
var newSpritesList = iter.Current.Value;
|
||||
|
||||
List<string> existSprites;
|
||||
if (m_allASprites.TryGetValue(atlasName, out existSprites))
|
||||
{
|
||||
if (existSprites.Count != newSpritesList.Count)
|
||||
{
|
||||
needSave = true;
|
||||
existSprites.Clear();
|
||||
existSprites.AddRange(newSpritesList);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < newSpritesList.Count; i++)
|
||||
{
|
||||
if (!existSprites.Contains(newSpritesList[i]))
|
||||
{
|
||||
needSave = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (needSave)
|
||||
{
|
||||
existSprites.Clear();
|
||||
existSprites.AddRange(newSpritesList);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
needSave = true;
|
||||
m_allASprites.Add(atlasName, new List<string>(newSpritesList));
|
||||
}
|
||||
|
||||
if (needSave && !needSaveAtlas.Contains(atlasName))
|
||||
{
|
||||
needSaveAtlas.Add(atlasName);
|
||||
}
|
||||
}
|
||||
iter.Dispose();
|
||||
foreach (var atlas in needSaveAtlas)
|
||||
{
|
||||
Debug.LogFormat("Gen atlas:{0}", atlas);
|
||||
SaveAtlas(atlas, true);
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
SpriteAtlasUtility.PackAllAtlases(EditorUserBuildSettings.activeBuildTarget);
|
||||
Debug.Log("Gen end");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e87a460a53ec5546a19e31705d13664
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b6b7bfca93e005f45999c16054d999e7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "BattleCore.Runtime",
|
||||
"rootNamespace": "BattleCore.Runtime",
|
||||
"references": [
|
||||
"GUID:aa06d4cc755c979489c256c1bcca1dfb",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b",
|
||||
"GUID:a90b2d3377c5e4a4db95cc44fb82045e"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 641632c4f8079b94f963b5284d859a12
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 890abd3a957e406ab422fc468ba6c169
|
||||
timeCreated: 1682353243
|
@@ -1,6 +0,0 @@
|
||||
namespace BattleCore.Runtime
|
||||
{
|
||||
public static class EntityExtension
|
||||
{
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4ef2dfa5ceac99458eb1745131a9c83
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,27 +0,0 @@
|
||||
using UnityEngine;
|
||||
using Unity.Mathematics;
|
||||
|
||||
namespace BattleCore.Runtime
|
||||
{
|
||||
public static class MathematicsExt
|
||||
{
|
||||
public static int2 ToInt2(this Vector2Int vec) => new int2(vec.x, vec.y);
|
||||
public static int3 ToInt3(this Vector3Int vec) => new int3(vec.x, vec.y, vec.z);
|
||||
public static float2 ToFloat2(this Vector2 vec) => new float2(vec.x, vec.y);
|
||||
public static float3 ToFloat3(this Vector3 vec) => new float3(vec.x, vec.y, vec.z);
|
||||
|
||||
public static bool IsEquals(this int2 a, int2 b) => math.all(a == b);
|
||||
public static bool IsEquals(this int3 a, int3 b) => math.all(a == b);
|
||||
|
||||
|
||||
public static Vector2Int ToVec2(this int2 vec) => new Vector2Int(vec.x, vec.y);
|
||||
public static Vector3Int ToVec3(this int2 vec) => new Vector3Int(vec.x, vec.y, 0);
|
||||
public static Vector3Int ToVec3(this int3 vec) => new Vector3Int(vec.x, vec.y, vec.z);
|
||||
public static Vector2 ToVec2(this float2 vec) => new Vector2(vec.x, vec.y);
|
||||
public static Vector3 ToVec3(this float3 vec) => new Vector3(vec.x, vec.y, vec.z);
|
||||
public static int ManhattanDist(this int2 vec) => vec.x + vec.y;
|
||||
public static int ManhattanDist(this int3 vec) => vec.x + vec.y + vec.z;
|
||||
public static float ManhattanDist(this float2 vec) => vec.x + vec.y;
|
||||
public static float ManhattanDist(this float3 vec) => vec.x + vec.y + vec.z;
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b0e288b918a41698571ec3d36059851
|
||||
timeCreated: 1682353251
|
@@ -1,21 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BattleCore.Runtime
|
||||
{
|
||||
public class Empty : MonoBehaviour
|
||||
{
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fc394f8c6ad5304a82ff84b4263756f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26079995c20c1b144a1c086bf2869375
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,33 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
#region Attribute
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class UpdateAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class FixedUpdateAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class LateUpdateAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class RoleLoginAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class RoleLogoutAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80791cccf63d44faa348884ea0c506a2
|
||||
timeCreated: 1684553027
|
@@ -1,16 +0,0 @@
|
||||
namespace GameBase
|
||||
{
|
||||
public class BaseClsTemplate<T>
|
||||
{
|
||||
protected static T Imp;
|
||||
|
||||
/// <summary>
|
||||
/// Unity工程,注册处理函数。
|
||||
/// </summary>
|
||||
/// <param name="imp">实现类。</param>
|
||||
public static void RegisterImp(T imp)
|
||||
{
|
||||
Imp = imp;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb7ef2f42b33ada47b3543dc7723fcb5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,79 +0,0 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 基础LogicSys,生命周期由TEngine实现,推荐给系统实现,
|
||||
/// 减少多余的Mono,保持系统层面只有一个Update。
|
||||
/// 用主Mono来驱动LogicSys的生命周期。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">逻辑系统类型。</typeparam>
|
||||
public abstract class BaseLogicSys<T> : ILogicSys where T : new()
|
||||
{
|
||||
private static T _instance;
|
||||
|
||||
public static bool HasInstance => _instance != null;
|
||||
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == _instance)
|
||||
{
|
||||
_instance = new T();
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
#region virtual function
|
||||
public virtual bool OnInit()
|
||||
{
|
||||
if (null == _instance)
|
||||
{
|
||||
_instance = new T();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual void OnStart()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnLateUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnFixedUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnRoleLogin()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnRoleLogout()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnDestroy()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnDrawGizmos()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnApplicationPause(bool pause)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnMapChanged()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc4ce19b17fd4277951d189b66f503e2
|
||||
timeCreated: 1683120353
|
@@ -1,263 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 通过LogicSys来驱动且具备Unity完整生命周期的单例(不继承MonoBehaviour)。
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract class BehaviourSingleton<T> : BaseBehaviourSingleton where T : BaseBehaviourSingleton, new()
|
||||
{
|
||||
private static T _instance;
|
||||
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == _instance)
|
||||
{
|
||||
_instance = new T();
|
||||
Log.Assert(_instance != null);
|
||||
_instance.Awake();
|
||||
RegSingleton(_instance);
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private static void RegSingleton(BaseBehaviourSingleton inst)
|
||||
{
|
||||
BehaviourSingleSystem.Instance.RegSingleton(inst);
|
||||
}
|
||||
}
|
||||
|
||||
public class BaseBehaviourSingleton
|
||||
{
|
||||
public bool IsStart = false;
|
||||
|
||||
public virtual void Active()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Awake()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual bool IsHaveLateUpdate()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void Start()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 帧更新。
|
||||
/// <remarks>需要UpdateAttribute。</remarks>
|
||||
/// </summary>
|
||||
public virtual void Update()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 后帧更新。
|
||||
/// <remarks>需要LateUpdateAttribute。</remarks>
|
||||
/// </summary>
|
||||
public virtual void LateUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 物理帧更新。
|
||||
/// <remarks>需要FixedUpdateAttribute。</remarks>
|
||||
/// </summary>
|
||||
public virtual void FixedUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Destroy()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnPause()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnResume()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnDrawGizmos()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class BehaviourSingleSystem : BaseLogicSys<BehaviourSingleSystem>
|
||||
{
|
||||
private readonly List<BaseBehaviourSingleton> _listInst = new List<BaseBehaviourSingleton>();
|
||||
private readonly List<BaseBehaviourSingleton> _listStart = new List<BaseBehaviourSingleton>();
|
||||
private readonly List<BaseBehaviourSingleton> _listUpdate = new List<BaseBehaviourSingleton>();
|
||||
private readonly List<BaseBehaviourSingleton> _listLateUpdate = new List<BaseBehaviourSingleton>();
|
||||
private readonly List<BaseBehaviourSingleton> _listFixedUpdate = new List<BaseBehaviourSingleton>();
|
||||
|
||||
public void RegSingleton(BaseBehaviourSingleton inst)
|
||||
{
|
||||
Log.Assert(!_listInst.Contains(inst));
|
||||
_listInst.Add(inst);
|
||||
_listStart.Add(inst);
|
||||
if (HadAttribute<UpdateAttribute>(inst.GetType()))
|
||||
{
|
||||
_listUpdate.Add(inst);
|
||||
}
|
||||
if (HadAttribute<LateUpdateAttribute>(inst.GetType()))
|
||||
{
|
||||
_listLateUpdate.Add(inst);
|
||||
}
|
||||
if (HadAttribute<FixedUpdateAttribute>(inst.GetType()))
|
||||
{
|
||||
_listFixedUpdate.Add(inst);
|
||||
}
|
||||
}
|
||||
|
||||
public void UnRegSingleton(BaseBehaviourSingleton inst)
|
||||
{
|
||||
if (inst == null)
|
||||
{
|
||||
Log.Error($"BaseBehaviourSingleton Is Null");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Assert(_listInst.Contains(inst));
|
||||
if (_listInst.Contains(inst))
|
||||
{
|
||||
_listInst.Remove(inst);
|
||||
}
|
||||
|
||||
if (_listStart.Contains(inst))
|
||||
{
|
||||
_listStart.Remove(inst);
|
||||
}
|
||||
|
||||
if (_listUpdate.Contains(inst))
|
||||
{
|
||||
_listUpdate.Remove(inst);
|
||||
}
|
||||
|
||||
if (_listLateUpdate.Contains(inst))
|
||||
{
|
||||
_listLateUpdate.Remove(inst);
|
||||
}
|
||||
|
||||
inst.Destroy();
|
||||
inst = null;
|
||||
}
|
||||
|
||||
public override void OnUpdate()
|
||||
{
|
||||
var listStart = _listStart;
|
||||
var listToUpdate = _listUpdate;
|
||||
var listToLateUpdate = _listLateUpdate;
|
||||
if (listStart.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < listStart.Count; i++)
|
||||
{
|
||||
var inst = listStart[i];
|
||||
Log.Assert(!inst.IsStart);
|
||||
|
||||
inst.IsStart = true;
|
||||
inst.Start();
|
||||
listToUpdate.Add(inst);
|
||||
|
||||
if (inst.IsHaveLateUpdate())
|
||||
{
|
||||
listToLateUpdate.Add(inst);
|
||||
}
|
||||
}
|
||||
|
||||
listStart.Clear();
|
||||
}
|
||||
|
||||
var listUpdateCnt = listToUpdate.Count;
|
||||
for (int i = 0; i < listUpdateCnt; i++)
|
||||
{
|
||||
var inst = listToUpdate[i];
|
||||
|
||||
TProfiler.BeginFirstSample(inst.GetType().FullName);
|
||||
inst.Update();
|
||||
TProfiler.EndFirstSample();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnLateUpdate()
|
||||
{
|
||||
var listLateUpdate = _listLateUpdate;
|
||||
var listLateUpdateCnt = listLateUpdate.Count;
|
||||
for (int i = 0; i < listLateUpdateCnt; i++)
|
||||
{
|
||||
var inst = listLateUpdate[i];
|
||||
|
||||
TProfiler.BeginFirstSample(inst.GetType().FullName);
|
||||
inst.LateUpdate();
|
||||
TProfiler.EndFirstSample();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnFixedUpdate()
|
||||
{
|
||||
var listFixedUpdate = _listFixedUpdate;
|
||||
var listFixedUpdateCnt = listFixedUpdate.Count;
|
||||
for (int i = 0; i < listFixedUpdateCnt; i++)
|
||||
{
|
||||
var inst = listFixedUpdate[i];
|
||||
|
||||
TProfiler.BeginFirstSample(inst.GetType().FullName);
|
||||
inst.FixedUpdate();
|
||||
TProfiler.EndFirstSample();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
for (int i = 0; i < _listInst.Count; i++)
|
||||
{
|
||||
var inst = _listInst[i];
|
||||
inst.Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnApplicationPause(bool pause)
|
||||
{
|
||||
for (int i = 0; i < _listInst.Count; i++)
|
||||
{
|
||||
var inst = _listInst[i];
|
||||
if (pause)
|
||||
{
|
||||
inst.OnPause();
|
||||
}
|
||||
else
|
||||
{
|
||||
inst.OnResume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDrawGizmos()
|
||||
{
|
||||
for (int i = 0; i < _listInst.Count; i++)
|
||||
{
|
||||
var inst = _listInst[i];
|
||||
inst.OnDrawGizmos();
|
||||
}
|
||||
}
|
||||
|
||||
private bool HadAttribute<T>(Type type) where T:Attribute
|
||||
{
|
||||
T attribute = Attribute.GetCustomAttribute(type, typeof(T)) as T;
|
||||
|
||||
return attribute != null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c0e9c1c8c9d4ce99a1c991fb62a0256
|
||||
timeCreated: 1683120460
|
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"name": "GameBase",
|
||||
"rootNamespace": "GameBase",
|
||||
"references": [
|
||||
"GUID:aa06d4cc755c979489c256c1bcca1dfb"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08c3762f54316454ca6b6fbcb22b40e5
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b062b3e32edd4536a4308a3d180842e0
|
||||
timeCreated: 1681989133
|
@@ -1,40 +0,0 @@
|
||||
using TEngine;
|
||||
|
||||
namespace GameBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 用来在多线程下检测耗时。
|
||||
/// </summary>
|
||||
public class GameTickWatcher
|
||||
{
|
||||
private long _startTick;
|
||||
|
||||
public GameTickWatcher()
|
||||
{
|
||||
Refresh();
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
_startTick = System.DateTime.Now.Ticks;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取用时。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public float ElapseTime()
|
||||
{
|
||||
long endTick = System.DateTime.Now.Ticks;
|
||||
return (float)((endTick - _startTick) / 10000) / 1000.0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 输出用时。
|
||||
/// </summary>
|
||||
public void LogUsedTime()
|
||||
{
|
||||
Log.Info($"Used Time: {this.ElapseTime()}");
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7320165f7aa147a998a30fe2f7a5a5c2
|
||||
timeCreated: 1681989139
|
@@ -1,58 +0,0 @@
|
||||
/// <summary>
|
||||
/// 定义通用的逻辑接口,统一生命期调用
|
||||
/// </summary>
|
||||
public interface ILogicSys
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化接口
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool OnInit();
|
||||
|
||||
/// <summary>
|
||||
/// 销毁系统
|
||||
/// </summary>
|
||||
void OnDestroy();
|
||||
|
||||
/// <summary>
|
||||
/// 初始化后,第一帧统一调用
|
||||
/// </summary>
|
||||
void OnStart();
|
||||
|
||||
/// <summary>
|
||||
/// 更新接口
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
void OnUpdate();
|
||||
|
||||
/// <summary>
|
||||
/// 渲染后调用
|
||||
/// </summary>
|
||||
void OnLateUpdate();
|
||||
|
||||
/// <summary>
|
||||
/// 物理帧更新
|
||||
/// </summary>
|
||||
void OnFixedUpdate();
|
||||
|
||||
/// <summary>
|
||||
/// 登录账号/角色时调用
|
||||
/// </summary>
|
||||
void OnRoleLogin();
|
||||
|
||||
/// <summary>
|
||||
/// 清理数据接口,切换账号/角色时调用
|
||||
/// </summary>
|
||||
void OnRoleLogout();
|
||||
|
||||
/// <summary>
|
||||
/// 绘制调试接口
|
||||
/// </summary>
|
||||
void OnDrawGizmos();
|
||||
|
||||
/// <summary>
|
||||
/// 暂停游戏
|
||||
/// </summary>
|
||||
/// <param name="pause"></param>
|
||||
void OnApplicationPause(bool pause);
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63ff6535a43f41d7ac793b8a153a37b6
|
||||
timeCreated: 1681213932
|
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dab5f3e08b4367d41b801af29d381ca8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,190 +0,0 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Linq;
|
||||
|
||||
/*******************************************************************************
|
||||
//开启一个Loom进程
|
||||
Loom.RunAsync(() =>
|
||||
{
|
||||
aucThread = new Thread(ReceiveMsg);
|
||||
aucThread.Start();
|
||||
}
|
||||
|
||||
//进程调用主线程方法
|
||||
MainPack pack = (MainPack)MainPack.Descriptor.Parser.ParseFrom(buffer, 0, len);
|
||||
Loom.QueueOnMainThread((param) =>
|
||||
{
|
||||
UdpHandleResponse(pack);
|
||||
}, null);
|
||||
|
||||
*******************************************************************************/
|
||||
namespace GameBase
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Loom多线程通信。
|
||||
/// <remarks></remarks>
|
||||
/// </summary>
|
||||
public class Loom : MonoBehaviour
|
||||
{
|
||||
public Dictionary<string, CancellationTokenSource> TokenSourcesDictionary = new Dictionary<string, CancellationTokenSource>();
|
||||
private static readonly int MaxThreads = 8;
|
||||
private static int _numThreads;
|
||||
private static Loom _current;
|
||||
|
||||
public static Loom Current
|
||||
{
|
||||
get
|
||||
{
|
||||
Initialize();
|
||||
return _current;
|
||||
}
|
||||
}
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
_current = this;
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
protected void OnDestroy()
|
||||
{
|
||||
}
|
||||
|
||||
private static bool _initialized;
|
||||
|
||||
private static void Initialize()
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
|
||||
var obj = new GameObject("[Loom]");
|
||||
|
||||
_current = obj.AddComponent<Loom>();
|
||||
|
||||
DontDestroyOnLoad(obj);
|
||||
}
|
||||
}
|
||||
|
||||
public struct NoDelayedQueueItem
|
||||
{
|
||||
public Action<object> Action;
|
||||
public object Param;
|
||||
}
|
||||
|
||||
private readonly List<NoDelayedQueueItem> _actions = new List<NoDelayedQueueItem>();
|
||||
|
||||
public struct DelayedQueueItem
|
||||
{
|
||||
public float Time;
|
||||
public Action<object> Action;
|
||||
public object Param;
|
||||
}
|
||||
|
||||
private readonly List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>();
|
||||
|
||||
private readonly List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>();
|
||||
|
||||
public static void QueueOnMainThread(Action<object> taction, object param, float time = 0f)
|
||||
{
|
||||
if (time != 0f)
|
||||
{
|
||||
lock (Current._delayed)
|
||||
{
|
||||
Current._delayed.Add(new DelayedQueueItem { Time = Time.time + time, Action = taction, Param = param });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (Current._actions)
|
||||
{
|
||||
Current._actions.Add(new NoDelayedQueueItem { Action = taction, Param = param });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Thread RunAsync(Action action)
|
||||
{
|
||||
Initialize();
|
||||
while (_numThreads >= MaxThreads)
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
|
||||
Interlocked.Increment(ref _numThreads);
|
||||
ThreadPool.QueueUserWorkItem(RunAction, action);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void RunAction(object action)
|
||||
{
|
||||
try
|
||||
{
|
||||
((Action)action)();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
finally
|
||||
{
|
||||
Interlocked.Decrement(ref _numThreads);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
if (_current == this)
|
||||
{
|
||||
_current = null;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<NoDelayedQueueItem> _currentActions = new List<NoDelayedQueueItem>();
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (_actions.Count > 0)
|
||||
{
|
||||
lock (_actions)
|
||||
{
|
||||
_currentActions.Clear();
|
||||
_currentActions.AddRange(_actions);
|
||||
_actions.Clear();
|
||||
}
|
||||
|
||||
for (int i = 0; i < _currentActions.Count; i++)
|
||||
{
|
||||
_currentActions[i].Action(_currentActions[i].Param);
|
||||
}
|
||||
}
|
||||
|
||||
if (_delayed.Count > 0)
|
||||
{
|
||||
lock (_delayed)
|
||||
{
|
||||
_currentDelayed.Clear();
|
||||
_currentDelayed.AddRange(_delayed.Where(d => d.Time <= Time.time));
|
||||
for (int i = 0; i < _currentDelayed.Count; i++)
|
||||
{
|
||||
_delayed.Remove(_currentDelayed[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _currentDelayed.Count; i++)
|
||||
{
|
||||
_currentDelayed[i].Action(_currentDelayed[i].Param);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eea4adc555e37f842abf5dd24c191d93
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 464445719fff48a78021df4a4a6b05a5
|
||||
timeCreated: 1684552621
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00565f0d362f4c36836804455e19c3df
|
||||
timeCreated: 1681990210
|
@@ -1,27 +0,0 @@
|
||||
using TEngine;
|
||||
|
||||
namespace GameBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 通用单例。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">泛型T。</typeparam>
|
||||
public class Singleton<T> where T : new()
|
||||
{
|
||||
private static T _instance;
|
||||
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == _instance)
|
||||
{
|
||||
_instance = new T();
|
||||
Log.Assert(_instance != null);
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b68a449df312429cbb27873984ec238e
|
||||
timeCreated: 1681214042
|
@@ -1,214 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using TEngine;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace GameBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 单例接口。
|
||||
/// </summary>
|
||||
public interface ISingleton
|
||||
{
|
||||
void Active();
|
||||
|
||||
void Release();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单例管理器(统一化持久和释放)。
|
||||
/// </summary>
|
||||
public static class SingletonMgr
|
||||
{
|
||||
private static List<ISingleton> _singletonList;
|
||||
private static Dictionary<string, GameObject> _gameObjects;
|
||||
private static GameObject _root;
|
||||
|
||||
public static GameObject Root
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_root == null)
|
||||
{
|
||||
_root = GameObject.Find("[GameModule]");
|
||||
|
||||
if (_root == null)
|
||||
{
|
||||
_root = new GameObject("[GameModule]")
|
||||
{
|
||||
transform =
|
||||
{
|
||||
position = Vector3.zero
|
||||
}
|
||||
};
|
||||
}
|
||||
Object.DontDestroyOnLoad(_root);
|
||||
}
|
||||
return _root;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Retain(ISingleton go)
|
||||
{
|
||||
if (_singletonList == null)
|
||||
{
|
||||
_singletonList = new List<ISingleton>();
|
||||
}
|
||||
|
||||
_singletonList.Add(go);
|
||||
}
|
||||
|
||||
public static void Retain(GameObject go)
|
||||
{
|
||||
if (_gameObjects == null)
|
||||
{
|
||||
_gameObjects = new Dictionary<string, GameObject>();
|
||||
}
|
||||
|
||||
if (!_gameObjects.ContainsKey(go.name))
|
||||
{
|
||||
_gameObjects.Add(go.name, go);
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
Object.DontDestroyOnLoad(go);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Release(GameObject go)
|
||||
{
|
||||
if (_gameObjects != null && _gameObjects.ContainsKey(go.name))
|
||||
{
|
||||
_gameObjects.Remove(go.name);
|
||||
Object.Destroy(go);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Release(ISingleton go)
|
||||
{
|
||||
if (_singletonList != null && _singletonList.Contains(go))
|
||||
{
|
||||
_singletonList.Remove(go);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Release()
|
||||
{
|
||||
if (_gameObjects != null)
|
||||
{
|
||||
foreach (var item in _gameObjects)
|
||||
{
|
||||
UnityEngine.Object.Destroy(item.Value);
|
||||
}
|
||||
|
||||
_gameObjects.Clear();
|
||||
}
|
||||
|
||||
if (_singletonList != null)
|
||||
{
|
||||
for (int i = 0; i < _singletonList.Count; ++i)
|
||||
{
|
||||
_singletonList[i].Release();
|
||||
}
|
||||
|
||||
_singletonList.Clear();
|
||||
}
|
||||
|
||||
Resources.UnloadUnusedAssets();
|
||||
}
|
||||
|
||||
public static GameObject GetGameObject(string name)
|
||||
{
|
||||
GameObject go = null;
|
||||
if (_gameObjects != null)
|
||||
{
|
||||
_gameObjects.TryGetValue(name, out go);
|
||||
}
|
||||
|
||||
return go;
|
||||
}
|
||||
|
||||
internal static bool ContainsKey(string name)
|
||||
{
|
||||
if (_gameObjects != null)
|
||||
{
|
||||
return _gameObjects.ContainsKey(name);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static ISingleton GetSingleton(string name)
|
||||
{
|
||||
for (int i = 0; i < _singletonList.Count; ++i)
|
||||
{
|
||||
if (_singletonList[i].ToString() == name)
|
||||
{
|
||||
return _singletonList[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 释放所有单例。
|
||||
/// </summary>
|
||||
public static void ReStart()
|
||||
{
|
||||
Release();
|
||||
|
||||
SceneManager.LoadScene(0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 全局单例对象(非线程安全)。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">泛型T。</typeparam>
|
||||
public abstract class TSingleton<T> : ISingleton where T : TSingleton<T>, new()
|
||||
{
|
||||
private static T _instance;
|
||||
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null == _instance)
|
||||
{
|
||||
_instance = new T();
|
||||
_instance.Init();
|
||||
#if UNITY_EDITOR
|
||||
Log.Info($"TSingleton Instance:{typeof(T).Name}");
|
||||
#endif
|
||||
SingletonMgr.Retain(_instance);
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsValid => _instance != null;
|
||||
|
||||
protected TSingleton()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void Init()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Active()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Release()
|
||||
{
|
||||
if (_instance != null)
|
||||
{
|
||||
SingletonMgr.Release(_instance);
|
||||
_instance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa2cb5bb622045d7a6f2a4c4faea3ca6
|
||||
timeCreated: 1681989590
|
@@ -1,114 +0,0 @@
|
||||
using TEngine;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 具备Unity完整生命周期的单例。
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract class UnitySingleton<T> : MonoBehaviour where T : MonoBehaviour
|
||||
{
|
||||
private static T _instance;
|
||||
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
var ins = FindObjectOfType<T>();
|
||||
if (ins != null)
|
||||
{
|
||||
var obj = ins.gameObject;
|
||||
obj.name = typeof(T).Name;
|
||||
_instance = ins;
|
||||
SingletonMgr.Retain(obj);
|
||||
return Instance;
|
||||
}
|
||||
|
||||
System.Type thisType = typeof(T);
|
||||
string instName = thisType.Name;
|
||||
GameObject go = SingletonMgr.GetGameObject(instName);
|
||||
if (go == null)
|
||||
{
|
||||
go = GameObject.Find($"[{instName}]");
|
||||
if (go == null)
|
||||
{
|
||||
go = new GameObject($"[{instName}]")
|
||||
{
|
||||
transform =
|
||||
{
|
||||
position = Vector3.zero
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
_instance = go.GetComponent<T>();
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = go.AddComponent<T>();
|
||||
}
|
||||
|
||||
if (_instance == null)
|
||||
{
|
||||
Log.Error($"Can't create UnitySingleton<{typeof(T)}>");
|
||||
}
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static T Active()
|
||||
{
|
||||
return Instance;
|
||||
}
|
||||
|
||||
public static bool IsValid => _instance != null;
|
||||
|
||||
private bool CheckInstance()
|
||||
{
|
||||
if (this == Instance)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
GameObject.Destroy(gameObject);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual void OnLoad()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Awake()
|
||||
{
|
||||
if (CheckInstance())
|
||||
{
|
||||
OnLoad();
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
Log.Debug($"UnitySingleton Instance:{typeof(T).Name}");
|
||||
#endif
|
||||
GameObject tEngine = SingletonMgr.Root;
|
||||
if (tEngine != null)
|
||||
{
|
||||
this.gameObject.transform.SetParent(tEngine.transform);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
public static void Release()
|
||||
{
|
||||
if (_instance == null) return;
|
||||
SingletonMgr.Release(_instance.gameObject);
|
||||
_instance = null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25c99243aa534df5870e36fdf9d36afd
|
||||
timeCreated: 1681990223
|
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d862c80fdc1e684e8ff3b6ae7707b79
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,24 +0,0 @@
|
||||
using TEngine;
|
||||
using UnityEngine;
|
||||
#if ENABLE_URP
|
||||
using UnityEngine.Rendering.Universal;
|
||||
#endif
|
||||
|
||||
namespace GameLogic
|
||||
{
|
||||
public class CameraUtils
|
||||
{
|
||||
public static void AddCameraStack(Camera camera,Camera mainCamera)
|
||||
{
|
||||
#if ENABLE_URP
|
||||
if (mainCamera != null)
|
||||
{
|
||||
// 通过脚本的方式,只要能找到 camera 不轮是否跨 base 相机的场景,都可以 Add 进 Stack
|
||||
mainCamera.GetComponent<UniversalAdditionalCameraData>().cameraStack.Add(GameModule.UI.UICamera);
|
||||
}
|
||||
#else
|
||||
Log.Fatal("Could not add camera stack because had no URP-Render-Pip");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6375b5490bbdcc145a24706a6c4e9cb7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,162 +0,0 @@
|
||||
using GameBase;
|
||||
using TEngine;
|
||||
|
||||
public partial class GameApp:Singleton<GameApp>
|
||||
{
|
||||
/// <summary>
|
||||
/// 热更域App主入口。
|
||||
/// </summary>
|
||||
/// <param name="objects"></param>
|
||||
public static void Entrance(object[] objects)
|
||||
{
|
||||
Log.Warning("======= 看到此条日志代表你成功运行了热更新代码 =======");
|
||||
Log.Warning("======= Entrance GameApp =======");
|
||||
Instance.Init();
|
||||
Instance.Start();
|
||||
Utility.Unity.AddUpdateListener(Instance.Update);
|
||||
Utility.Unity.AddFixedUpdateListener(Instance.FixedUpdate);
|
||||
Utility.Unity.AddLateUpdateListener(Instance.LateUpdate);
|
||||
Utility.Unity.AddDestroyListener(Instance.OnDestroy);
|
||||
Utility.Unity.AddOnDrawGizmosListener(Instance.OnDrawGizmos);
|
||||
Utility.Unity.AddOnApplicationPauseListener(Instance.OnApplicationPause);
|
||||
Instance.StartGameLogic();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始游戏业务层逻辑。
|
||||
/// <remarks>显示UI、加载场景等。</remarks>
|
||||
/// </summary>
|
||||
private void StartGameLogic()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭游戏。
|
||||
/// </summary>
|
||||
/// <param name="shutdownType">关闭游戏框架类型。</param>
|
||||
public static void Shutdown(ShutdownType shutdownType)
|
||||
{
|
||||
|
||||
if (shutdownType == ShutdownType.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (shutdownType == ShutdownType.Restart)
|
||||
{
|
||||
Utility.Unity.RemoveUpdateListener(Instance.Update);
|
||||
Utility.Unity.RemoveFixedUpdateListener(Instance.FixedUpdate);
|
||||
Utility.Unity.RemoveLateUpdateListener(Instance.LateUpdate);
|
||||
Utility.Unity.RemoveDestroyListener(Instance.OnDestroy);
|
||||
Utility.Unity.RemoveOnDrawGizmosListener(Instance.OnDrawGizmos);
|
||||
Utility.Unity.RemoveOnApplicationPauseListener(Instance.OnApplicationPause);
|
||||
return;
|
||||
}
|
||||
|
||||
if (shutdownType == ShutdownType.Quit)
|
||||
{
|
||||
UnityEngine.Application.Quit();
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorApplication.isPlaying = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
GameTime.StartFrame();
|
||||
var listLogic = _listLogicMgr;
|
||||
var logicCnt = listLogic.Count;
|
||||
for (int i = 0; i < logicCnt; i++)
|
||||
{
|
||||
var logic = listLogic[i];
|
||||
logic.OnStart();
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
GameTime.StartFrame();
|
||||
TProfiler.BeginFirstSample("Update");
|
||||
var listLogic = _listLogicMgr;
|
||||
var logicCnt = listLogic.Count;
|
||||
for (int i = 0; i < logicCnt; i++)
|
||||
{
|
||||
var logic = listLogic[i];
|
||||
TProfiler.BeginSample(logic.GetType().FullName);
|
||||
logic.OnUpdate();
|
||||
TProfiler.EndSample();
|
||||
}
|
||||
TProfiler.EndFirstSample();
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
GameTime.StartFrame();
|
||||
TProfiler.BeginFirstSample("FixedUpdate");
|
||||
var listLogic = _listLogicMgr;
|
||||
var logicCnt = listLogic.Count;
|
||||
for (int i = 0; i < logicCnt; i++)
|
||||
{
|
||||
var logic = listLogic[i];
|
||||
TProfiler.BeginSample(logic.GetType().FullName);
|
||||
logic.OnFixedUpdate();
|
||||
TProfiler.EndSample();
|
||||
}
|
||||
TProfiler.EndFirstSample();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
GameTime.StartFrame();
|
||||
TProfiler.BeginFirstSample("LateUpdate");
|
||||
var listLogic = _listLogicMgr;
|
||||
var logicCnt = listLogic.Count;
|
||||
for (int i = 0; i < logicCnt; i++)
|
||||
{
|
||||
var logic = listLogic[i];
|
||||
TProfiler.BeginSample(logic.GetType().FullName);
|
||||
logic.OnLateUpdate();
|
||||
TProfiler.EndSample();
|
||||
}
|
||||
TProfiler.EndFirstSample();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
GameTime.StartFrame();
|
||||
var listLogic = _listLogicMgr;
|
||||
var logicCnt = listLogic.Count;
|
||||
for (int i = 0; i < logicCnt; i++)
|
||||
{
|
||||
var logic = listLogic[i];
|
||||
logic.OnDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
GameTime.StartFrame();
|
||||
var listLogic = _listLogicMgr;
|
||||
var logicCnt = listLogic.Count;
|
||||
for (int i = 0; i < logicCnt; i++)
|
||||
{
|
||||
var logic = listLogic[i];
|
||||
logic.OnDrawGizmos();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private void OnApplicationPause(bool isPause)
|
||||
{
|
||||
var listLogic = _listLogicMgr;
|
||||
var logicCnt = listLogic.Count;
|
||||
for (int i = 0; i < logicCnt; i++)
|
||||
{
|
||||
var logic = listLogic[i];
|
||||
logic.OnApplicationPause(isPause);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,55 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using TEngine;
|
||||
|
||||
public partial class GameApp
|
||||
{
|
||||
private List<ILogicSys> _listLogicMgr;
|
||||
|
||||
private void Init()
|
||||
{
|
||||
_listLogicMgr = new List<ILogicSys>();
|
||||
RegisterAllSystem();
|
||||
InitSystemSetting();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置一些通用的系统属性。
|
||||
/// </summary>
|
||||
private void InitSystemSetting()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册所有逻辑系统
|
||||
/// </summary>
|
||||
private void RegisterAllSystem()
|
||||
{
|
||||
//带生命周期的单例系统。
|
||||
AddLogicSys(BehaviourSingleSystem.Instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册逻辑系统。
|
||||
/// </summary>
|
||||
/// <param name="logicSys">ILogicSys</param>
|
||||
/// <returns></returns>
|
||||
protected bool AddLogicSys(ILogicSys logicSys)
|
||||
{
|
||||
if (_listLogicMgr.Contains(logicSys))
|
||||
{
|
||||
Log.Fatal("Repeat add logic system: {0}", logicSys.GetType().Name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!logicSys.OnInit())
|
||||
{
|
||||
Log.Fatal("{0} Init failed", logicSys.GetType().Name);
|
||||
return false;
|
||||
}
|
||||
|
||||
_listLogicMgr.Add(logicSys);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4703541a565f5ec4bb35edd81c28958c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"name": "GameLogic",
|
||||
"rootNamespace": "GameLogic",
|
||||
"references": [
|
||||
"GUID:08c3762f54316454ca6b6fbcb22b40e5",
|
||||
"GUID:a90b2d3377c5e4a4db95cc44fb82045e",
|
||||
"GUID:aa06d4cc755c979489c256c1bcca1dfb",
|
||||
"GUID:641632c4f8079b94f963b5284d859a12",
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f",
|
||||
"GUID:15fc0a57446b3144c949da3e2b9737a9"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.render-pipelines.universal",
|
||||
"expression": "",
|
||||
"define": "ENABLE_URP"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 145b951be40d41dea06e76bd967a5d15
|
||||
timeCreated: 1682045847
|
@@ -1,166 +0,0 @@
|
||||
using TEngine;
|
||||
|
||||
namespace GameLogic
|
||||
{
|
||||
public enum ClientConnectWatcherStatus
|
||||
{
|
||||
StatusInit,
|
||||
StatusReconnectAuto,
|
||||
StatusReconnectConfirm,
|
||||
StatusWaitExit
|
||||
}
|
||||
|
||||
public class ClientConnectWatcher
|
||||
{
|
||||
private readonly GameClient _client;
|
||||
private ClientConnectWatcherStatus _status;
|
||||
private float _statusTime;
|
||||
private int _reconnectCnt = 0;
|
||||
private int _disconnectReason = 0;
|
||||
|
||||
private bool _enable = false;
|
||||
|
||||
public bool Enable
|
||||
{
|
||||
get => _enable;
|
||||
set
|
||||
{
|
||||
if (_enable != value)
|
||||
{
|
||||
_enable = value;
|
||||
if (_enable)
|
||||
{
|
||||
OnEnable();
|
||||
}
|
||||
else
|
||||
{
|
||||
OnDisable();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ClientConnectWatcherStatus Status
|
||||
{
|
||||
get => _status;
|
||||
set
|
||||
{
|
||||
if (_status == value) return;
|
||||
_status = value;
|
||||
_statusTime = NowTime;
|
||||
}
|
||||
}
|
||||
|
||||
private float NowTime => GameTime.unscaledTime;
|
||||
|
||||
public ClientConnectWatcher(GameClient client)
|
||||
{
|
||||
_client = client;
|
||||
_statusTime = NowTime;
|
||||
_status = ClientConnectWatcherStatus.StatusInit;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (!_enable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_client.IsEntered)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_status)
|
||||
{
|
||||
case ClientConnectWatcherStatus.StatusInit:
|
||||
UpdateOnInitStatus();
|
||||
break;
|
||||
case ClientConnectWatcherStatus.StatusReconnectAuto:
|
||||
UpdateOnReconnectAuto();
|
||||
break;
|
||||
case ClientConnectWatcherStatus.StatusReconnectConfirm:
|
||||
UpdateOnReconnectConfirm();
|
||||
break;
|
||||
case ClientConnectWatcherStatus.StatusWaitExit:
|
||||
UpdateOnWaitExit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnReConnect()
|
||||
{
|
||||
if (_status == ClientConnectWatcherStatus.StatusReconnectConfirm)
|
||||
{
|
||||
Status = ClientConnectWatcherStatus.StatusReconnectAuto;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateOnInitStatus()
|
||||
{
|
||||
int autoReconnectMaxCount = 4;
|
||||
if (_reconnectCnt <= autoReconnectMaxCount)
|
||||
{
|
||||
if (_reconnectCnt == 0)
|
||||
{
|
||||
_disconnectReason = _client.LastNetErrCode;
|
||||
}
|
||||
|
||||
Status = ClientConnectWatcherStatus.StatusReconnectAuto;
|
||||
_reconnectCnt++;
|
||||
|
||||
//重连
|
||||
_client.Reconnect();
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ClientConnectWatcherStatus.StatusReconnectConfirm;
|
||||
_reconnectCnt++;
|
||||
// UISys.Mgr.ShowUI(GAME_UI_TYPE.Tip_NetDisconn, UISys.Mgr.GetUIWindowParam().SetParam("errCode", m_disconnectReason));
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateOnReconnectAuto()
|
||||
{
|
||||
if (_client.IsEntered)
|
||||
{
|
||||
Status = ClientConnectWatcherStatus.StatusInit;
|
||||
_reconnectCnt = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
float nowTime = NowTime;
|
||||
var timeoutTime = 10f;
|
||||
|
||||
if (_statusTime + timeoutTime < nowTime)
|
||||
{
|
||||
Log.Error("UpdateOnReconnectAuto timeout: {0}", timeoutTime);
|
||||
|
||||
//切换到默认的,下一帧继续判断是否需要自动还是手动
|
||||
Status = ClientConnectWatcherStatus.StatusInit;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateOnReconnectConfirm()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UpdateOnWaitExit()
|
||||
{
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
Status = ClientConnectWatcherStatus.StatusInit;
|
||||
_reconnectCnt = 0;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
Status = ClientConnectWatcherStatus.StatusInit;
|
||||
_reconnectCnt = 0;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e4e637f3da340dd9512150c3e2ff087
|
||||
timeCreated: 1684334948
|
@@ -1,428 +0,0 @@
|
||||
using System.Net.Sockets;
|
||||
using GameBase;
|
||||
using GameProto;
|
||||
using TEngine;
|
||||
using CSPkg = GameProto.CSPkg;
|
||||
|
||||
namespace GameLogic
|
||||
{
|
||||
public enum GameClientStatus
|
||||
{
|
||||
StatusInit, //初始化
|
||||
StatusReconnect, //重新连接
|
||||
StatusClose, //断开连接
|
||||
StatusLogin, //登录中
|
||||
StatusEnter, //AccountLogin成功,进入服务器了
|
||||
}
|
||||
|
||||
public enum CsMsgResult
|
||||
{
|
||||
NoError = 0,
|
||||
NetworkError = 1,
|
||||
InternalError = 2,
|
||||
MsgTimeOut = 3,
|
||||
PingTimeOut = 4,
|
||||
}
|
||||
|
||||
//定义消息回报的回调接口
|
||||
public delegate void CsMsgDelegate(CsMsgResult result, CSPkg msg);
|
||||
|
||||
/// <summary>
|
||||
/// 统计网络协议的接口
|
||||
/// </summary>
|
||||
public delegate void CsMsgStatDelegate(int cmdID, int pkgSize);
|
||||
|
||||
public class GameClient : Singleton<GameClient>
|
||||
{
|
||||
private readonly INetworkChannel _channel;
|
||||
|
||||
private GameClientStatus _status = GameClientStatus.StatusInit;
|
||||
|
||||
private readonly MsgDispatcher _dispatcher;
|
||||
|
||||
private readonly ClientConnectWatcher _connectWatcher;
|
||||
|
||||
private float _lastLogDisconnectErrTime = 0f;
|
||||
|
||||
private int _lastNetErrCode = 0;
|
||||
|
||||
public int LastNetErrCode => _lastNetErrCode;
|
||||
|
||||
public GameClientStatus Status
|
||||
{
|
||||
get => _status;
|
||||
set => _status = value;
|
||||
}
|
||||
|
||||
public bool IsEntered => _status == GameClientStatus.StatusEnter;
|
||||
|
||||
/// <summary>
|
||||
/// 连续心跳超时
|
||||
/// </summary>
|
||||
private int _heatBeatTimeoutNum = 0;
|
||||
|
||||
private int _ping = -1;
|
||||
|
||||
private float NowTime => GameTime.unscaledTime;
|
||||
|
||||
private string _lastHost = null;
|
||||
private int _lastPort = 0;
|
||||
|
||||
public GameClient()
|
||||
{
|
||||
_connectWatcher = new ClientConnectWatcher(this);
|
||||
_dispatcher = new MsgDispatcher();
|
||||
_dispatcher.SetTimeout(5f);
|
||||
GameEvent.AddEventListener<INetworkChannel,object>(NetworkEvent.NetworkConnectedEvent,OnNetworkConnected);
|
||||
GameEvent.AddEventListener<INetworkChannel>(NetworkEvent.NetworkClosedEvent,OnNetworkClosed);
|
||||
GameEvent.AddEventListener<INetworkChannel,NetworkErrorCode,SocketError,string>(NetworkEvent.NetworkErrorEvent,OnNetworkError);
|
||||
GameEvent.AddEventListener<INetworkChannel,object>(NetworkEvent.NetworkCustomErrorEvent,OnNetworkCustomError);
|
||||
_channel = Network.Instance.CreateNetworkChannel("GameClient", ServiceType.Tcp, new NetworkChannelHelper());
|
||||
}
|
||||
|
||||
private void OnNetworkConnected(INetworkChannel channel, object userdata)
|
||||
{
|
||||
bool isReconnect = (_status == GameClientStatus.StatusReconnect);
|
||||
//准备登录
|
||||
Status = GameClientStatus.StatusLogin;
|
||||
|
||||
OnServerConnected(isReconnect);
|
||||
}
|
||||
|
||||
private void OnNetworkClosed(INetworkChannel channel)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void OnNetworkError(INetworkChannel channel, NetworkErrorCode networkErrorCode, SocketError socketError, string errorMessage)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void OnNetworkCustomError(INetworkChannel channel, object userData)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Connect(string host, int port, bool reconnect = false)
|
||||
{
|
||||
ResetParam();
|
||||
if (!reconnect)
|
||||
{
|
||||
SetWatchReconnect(false);
|
||||
}
|
||||
|
||||
if (reconnect)
|
||||
{
|
||||
// GameEvent.Get<ICommUI>().ShowWaitUITip(WaitUISeq.LOGINWORLD_SEQID, G.R(TextDefine.ID_TIPS_RECONNECTING));
|
||||
}
|
||||
else
|
||||
{
|
||||
// GameEvent.Get<ICommUI>().ShowWaitUI(WaitUISeq.LOGINWORLD_SEQID);
|
||||
}
|
||||
|
||||
_lastHost = host;
|
||||
_lastPort = port;
|
||||
|
||||
Status = reconnect ? GameClientStatus.StatusReconnect : GameClientStatus.StatusInit;
|
||||
|
||||
_channel.Connect(host, port);
|
||||
}
|
||||
|
||||
public void Reconnect()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_lastHost) || _lastPort <= 0)
|
||||
{
|
||||
// GameModule.UI.ShowTipMsg("Invalid reconnect param");
|
||||
return;
|
||||
}
|
||||
|
||||
_connectWatcher.OnReConnect();
|
||||
Connect(_lastHost, _lastPort, true);
|
||||
}
|
||||
|
||||
|
||||
public void Shutdown()
|
||||
{
|
||||
_channel.Close();
|
||||
_status = GameClientStatus.StatusInit;
|
||||
}
|
||||
|
||||
public void OnServerConnected(bool isReconnect)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool SendCsMsg(CSPkg reqPkg)
|
||||
{
|
||||
if (!IsStatusCanSendMsg(reqPkg.Head.MsgId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return DoSendData(reqPkg);
|
||||
}
|
||||
|
||||
public bool IsStatusCanSendMsg(uint msgId)
|
||||
{
|
||||
bool canSend = false;
|
||||
if (_status == GameClientStatus.StatusLogin)
|
||||
{
|
||||
canSend = (msgId == (uint)CSMsgID.CsCmdActLoginReq);
|
||||
}
|
||||
|
||||
if (_status == GameClientStatus.StatusEnter)
|
||||
{
|
||||
canSend = true;
|
||||
}
|
||||
|
||||
if (!canSend)
|
||||
{
|
||||
float nowTime = NowTime;
|
||||
if (_lastLogDisconnectErrTime + 5 < nowTime)
|
||||
{
|
||||
Log.Error("GameClient not connected, send msg failed, msgId[{0}]", msgId);
|
||||
_lastLogDisconnectErrTime = nowTime;
|
||||
}
|
||||
|
||||
//UISys.Mgr.ShowTipMsg(TextDefine.ID_ERR_NETWORKD_DISCONNECT);
|
||||
}
|
||||
|
||||
return canSend;
|
||||
}
|
||||
|
||||
public bool SendCsMsg(CSPkg reqPkg, uint resCmd, CsMsgDelegate resHandler = null, bool needShowWaitUI = true)
|
||||
{
|
||||
if (!IsStatusCanSendMsg(reqPkg.Head.MsgId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var ret = DoSendData(reqPkg);
|
||||
if (!ret)
|
||||
{
|
||||
if (resHandler != null)
|
||||
{
|
||||
resHandler(CsMsgResult.InternalError, null);
|
||||
}
|
||||
|
||||
_dispatcher.NotifyCmdError(resCmd, CsMsgResult.InternalError);
|
||||
}
|
||||
else
|
||||
{
|
||||
//注册消息
|
||||
if (resHandler != null)
|
||||
{
|
||||
_dispatcher.RegSeqHandle(reqPkg.Head.Echo, resCmd, resHandler);
|
||||
if (reqPkg.Head.Echo > 0 && IsWaitingCmd(resCmd) && needShowWaitUI)
|
||||
{
|
||||
// TODO
|
||||
// GameEvent.Get<ICommUI>().ShowWaitUI(reqPkg.Head.Echo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private bool DoSendData(CSPkg reqPkg)
|
||||
{
|
||||
if (!IsIgnoreLog(reqPkg.Head.MsgId))
|
||||
{
|
||||
Log.Debug("[c-s] CmdId[{0}]\n{1}", reqPkg.Head.MsgId, reqPkg.Body.ToString());
|
||||
}
|
||||
var sendRet = _channel.Send(reqPkg);
|
||||
return sendRet;
|
||||
}
|
||||
|
||||
private bool IsIgnoreLog(uint msgId)
|
||||
{
|
||||
bool ignoreLog = false;
|
||||
switch (msgId)
|
||||
{
|
||||
case (uint)CSMsgID.CsCmdHeatbeatReq:
|
||||
case (uint)CSMsgID.CsCmdHeatbeatRes:
|
||||
ignoreLog = true;
|
||||
break;
|
||||
}
|
||||
return ignoreLog;
|
||||
}
|
||||
|
||||
public static bool IsWaitingCmd(uint msgId)
|
||||
{
|
||||
//心跳包不需要读条等待
|
||||
if (msgId == (uint)CSMsgID.CsCmdHeatbeatRes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ResetParam()
|
||||
{
|
||||
_lastLogDisconnectErrTime = 0f;
|
||||
_heatBeatTimeoutNum = 0;
|
||||
_lastHbTime = 0f;
|
||||
_ping = -1;
|
||||
_lastNetErrCode = 0;
|
||||
}
|
||||
|
||||
public void OnUpdate()
|
||||
{
|
||||
_dispatcher.Update();
|
||||
TickHeartBeat();
|
||||
CheckHeatBeatTimeout();
|
||||
_connectWatcher.Update();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册静态消息
|
||||
/// </summary>
|
||||
/// <param name="iCmdID"></param>
|
||||
/// <param name="msgDelegate"></param>
|
||||
public void RegCmdHandle(int iCmdID, CsMsgDelegate msgDelegate)
|
||||
{
|
||||
_dispatcher.RegCmdHandle((uint)iCmdID, msgDelegate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除消息处理函数
|
||||
/// </summary>
|
||||
/// <param name="cmdId"></param>
|
||||
/// <param name="msgDelegate"></param>
|
||||
public void RmvCmdHandle(int cmdId, CsMsgDelegate msgDelegate)
|
||||
{
|
||||
_dispatcher.RmvCmdHandle((uint)cmdId, msgDelegate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置加密密钥
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
public void SetEncryptKey(string key)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置是否需要监控网络重连。
|
||||
/// 登录成功后,开启监控,可以自动重连或者提示玩家重连。
|
||||
/// </summary>
|
||||
/// <param name="needWatch"></param>
|
||||
public void SetWatchReconnect(bool needWatch)
|
||||
{
|
||||
_connectWatcher.Enable = needWatch;
|
||||
}
|
||||
|
||||
public bool IsNetworkOkAndLogin()
|
||||
{
|
||||
return _status == GameClientStatus.StatusEnter;
|
||||
}
|
||||
|
||||
#region 心跳处理
|
||||
|
||||
/// <summary>
|
||||
/// 最近一次心跳的时间
|
||||
/// </summary>
|
||||
private float _lastHbTime = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// 心跳间隔
|
||||
/// </summary>
|
||||
private readonly float _heartBeatDurTime = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 心跳超时的最大次数
|
||||
/// </summary>
|
||||
private const int HeatBeatTimeoutMaxCount = 2;
|
||||
|
||||
private bool CheckHeatBeatTimeout()
|
||||
{
|
||||
if (_heatBeatTimeoutNum >= HeatBeatTimeoutMaxCount)
|
||||
{
|
||||
//断开连接
|
||||
Shutdown();
|
||||
|
||||
//准备重连
|
||||
_heatBeatTimeoutNum = 0;
|
||||
Status = GameClientStatus.StatusClose;
|
||||
Log.Error("heat beat detect timeout");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TickHeartBeat()
|
||||
{
|
||||
if (Status != GameClientStatus.StatusEnter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var nowTime = NowTime;
|
||||
if (_lastHbTime + _heartBeatDurTime < nowTime)
|
||||
{
|
||||
_lastHbTime = nowTime;
|
||||
|
||||
CSPkg heatPkg = ProtobufUtility.BuildCsMsg((int)CSMsgID.CsCmdHeatbeatReq);
|
||||
heatPkg.Body.HeatBeatReq = new CSHeatBeatReq { HeatEchoTime = _lastHbTime };
|
||||
SendCsMsg(heatPkg, (int)CSMsgID.CsCmdHeatbeatRes, HandleHeatBeatRes);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleHeatBeatRes(CsMsgResult result, CSPkg msg)
|
||||
{
|
||||
if (result != CsMsgResult.NoError)
|
||||
{
|
||||
//如果是超时了,则标记最近收到包的次数
|
||||
if (result == CsMsgResult.MsgTimeOut)
|
||||
{
|
||||
_heatBeatTimeoutNum++;
|
||||
Log.Warning("heat beat timeout: {0}", _heatBeatTimeoutNum);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var resBody = msg.Body.HeatBeatRes;
|
||||
float diffTime = NowTime - resBody.HeatEchoTime;
|
||||
_ping = (int)(diffTime * 1000);
|
||||
_heatBeatTimeoutNum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Ping值
|
||||
|
||||
/// <summary>
|
||||
/// ping值
|
||||
/// </summary>
|
||||
public int Ping
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsPingValid())
|
||||
{
|
||||
return _ping / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsPingValid()
|
||||
{
|
||||
if (IsNetworkOkAndLogin())
|
||||
{
|
||||
return _ping >= 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c5441725c9f4d98a7790dc76a6a0c48
|
||||
timeCreated: 1684331687
|
@@ -1,265 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using GameProto;
|
||||
using TEngine;
|
||||
using CSPkg = GameProto.CSPkg;
|
||||
|
||||
namespace GameLogic
|
||||
{
|
||||
internal class MsgHandleDataToRmv
|
||||
{
|
||||
public uint MsgId;
|
||||
public CsMsgDelegate Handle;
|
||||
};
|
||||
|
||||
class MsgDispatcher
|
||||
{
|
||||
const int CheckTimeoutPerframe = 10;
|
||||
const int MaxMsgHandle = 256;
|
||||
|
||||
private readonly CsMsgDelegate[] _aMsgHandles = new CsMsgDelegate[MaxMsgHandle];
|
||||
private readonly float[] _fMsgRegTime = new float[MaxMsgHandle];
|
||||
private readonly UInt32[] _adwMsgRegSeq = new UInt32[MaxMsgHandle]; //因为_aiMsgRegResCmdID存储的是hash,不能保证一定seqid一样,所以这儿存储下,用来校验
|
||||
private readonly uint[] _aiMsgRegResCmdID = new uint[MaxMsgHandle];
|
||||
|
||||
UInt32 _dwLastCheckIndex = 0;
|
||||
|
||||
private readonly Dictionary<uint, List<CsMsgDelegate>> _mapCmdHandle = new Dictionary<uint, List<CsMsgDelegate>>();
|
||||
private readonly List<CsMsgStatDelegate> _listStatHandle = new List<CsMsgStatDelegate>();
|
||||
|
||||
//防止在处理消息的时候又删除了消息映射,所以这儿加了个队列来做个保护
|
||||
private readonly List<MsgHandleDataToRmv> _rmvList = new List<MsgHandleDataToRmv>();
|
||||
private bool _isInHandleLoop = false;
|
||||
private float _timeout = 5;
|
||||
|
||||
// 清理所有的网络消息
|
||||
public void CleanAllNetMsg()
|
||||
{
|
||||
_mapCmdHandle.Clear();
|
||||
}
|
||||
|
||||
public void SetTimeout(float timeout)
|
||||
{
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
public void RegSeqHandle(UInt32 dwMsgSeqID, uint iResCmdID, CsMsgDelegate msgDelegate)
|
||||
{
|
||||
UInt32 hashIndex = dwMsgSeqID % MaxMsgHandle;
|
||||
if (_aMsgHandles[hashIndex] != null)
|
||||
{
|
||||
OnCallSeqHandle(_adwMsgRegSeq[hashIndex], _aiMsgRegResCmdID[hashIndex]);
|
||||
NotifyTimeout(_aMsgHandles[hashIndex]);
|
||||
RmvReg((int)hashIndex);
|
||||
}
|
||||
|
||||
_aMsgHandles[hashIndex] = msgDelegate;
|
||||
_fMsgRegTime[hashIndex] = NowTime;
|
||||
_adwMsgRegSeq[hashIndex] = dwMsgSeqID;
|
||||
_aiMsgRegResCmdID[hashIndex] = iResCmdID;
|
||||
}
|
||||
|
||||
public void RegCmdHandle(uint iCmdID, CsMsgDelegate msgDelegate)
|
||||
{
|
||||
if (!_mapCmdHandle.TryGetValue(iCmdID, out var listHandle))
|
||||
{
|
||||
listHandle = new List<CsMsgDelegate>();
|
||||
_mapCmdHandle[iCmdID] = listHandle;
|
||||
}
|
||||
|
||||
if (listHandle != null)
|
||||
{
|
||||
if (listHandle.Contains(msgDelegate))
|
||||
{
|
||||
Log.Error("-------------repeat RegCmdHandle:{0}-----------", iCmdID);
|
||||
}
|
||||
|
||||
listHandle.Add(msgDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册统计处理接口
|
||||
/// </summary>
|
||||
/// <param name="handler"></param>
|
||||
public void RegCmdStatHandle(CsMsgStatDelegate handler)
|
||||
{
|
||||
_listStatHandle.Add(handler);
|
||||
}
|
||||
|
||||
public void DispatchCmdStat(int cmdID, int pkgSize)
|
||||
{
|
||||
foreach (CsMsgStatDelegate handle in _listStatHandle)
|
||||
{
|
||||
handle(cmdID, pkgSize);
|
||||
}
|
||||
}
|
||||
|
||||
public void RmvCmdHandle(uint iCmdID, CsMsgDelegate msgDelegate)
|
||||
{
|
||||
if (_isInHandleLoop)
|
||||
{
|
||||
MsgHandleDataToRmv toRmvData = new MsgHandleDataToRmv();
|
||||
toRmvData.MsgId = iCmdID;
|
||||
toRmvData.Handle = msgDelegate;
|
||||
|
||||
_rmvList.Add(toRmvData);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_mapCmdHandle.TryGetValue(iCmdID, out var listHandle))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (listHandle != null)
|
||||
{
|
||||
listHandle.Remove(msgDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
public void NotifyCmdError(uint iCmdID, CsMsgResult result)
|
||||
{
|
||||
NotifyCmdHandle(iCmdID, result, default(CSPkg));
|
||||
}
|
||||
|
||||
protected bool NotifyCmdHandle(uint cmdID, CsMsgResult result, CSPkg pkg)
|
||||
{
|
||||
bool ret = false;
|
||||
if (_mapCmdHandle.TryGetValue(cmdID, out var listHandle))
|
||||
{
|
||||
_isInHandleLoop = true;
|
||||
|
||||
var rmvList = _rmvList;
|
||||
rmvList.Clear();
|
||||
foreach (CsMsgDelegate handle in listHandle)
|
||||
{
|
||||
ret = true;
|
||||
|
||||
TProfiler.BeginSample("handle");
|
||||
handle(result, pkg);
|
||||
TProfiler.EndSample();
|
||||
}
|
||||
|
||||
_isInHandleLoop = false;
|
||||
|
||||
//再统一删除掉
|
||||
int rmvCnt = rmvList.Count;
|
||||
for (int i = 0; i < rmvCnt; i++)
|
||||
{
|
||||
var rmvItem = rmvList[i];
|
||||
Log.Error("-------------remove cmd handle on loop:{0}-----------", rmvItem.MsgId);
|
||||
RmvCmdHandle(rmvItem.MsgId, rmvItem.Handle);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected void OnCallSeqHandle(UInt32 echoSeq, uint resCmdID)
|
||||
{
|
||||
if (echoSeq > 0)
|
||||
{
|
||||
// TODO
|
||||
// GameEvent.Get<ICommUI>().FinWaitUI(echoSeq);
|
||||
}
|
||||
}
|
||||
|
||||
protected void NotifyTimeout(CsMsgDelegate msgHandler)
|
||||
{
|
||||
msgHandler(CsMsgResult.MsgTimeOut, default(CSPkg));
|
||||
}
|
||||
|
||||
public void NotifySeqError(UInt32 dwSeqID, CsMsgResult result)
|
||||
{
|
||||
UInt32 hashIndex = dwSeqID % MaxMsgHandle;
|
||||
|
||||
//先判断是否有注册的指定消息
|
||||
if (_aMsgHandles[hashIndex] != null &&
|
||||
_adwMsgRegSeq[hashIndex] == dwSeqID)
|
||||
{
|
||||
OnCallSeqHandle(dwSeqID, _aiMsgRegResCmdID[hashIndex]);
|
||||
_aMsgHandles[hashIndex](result, null);
|
||||
|
||||
RmvReg((int)hashIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsCmdFilterNoLog(int cmdID)
|
||||
{
|
||||
switch (cmdID)
|
||||
{
|
||||
case (int)CSMsgID.CsCmdHeatbeatRes:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void NotifyMsg(CSPkg msg)
|
||||
{
|
||||
UInt32 dwSeq = msg.Head.Echo;
|
||||
UInt32 hashIndex = dwSeq % MaxMsgHandle;
|
||||
//判断是否有固定的消息处理流程
|
||||
bool bHaveHandle = NotifyCmdHandle(msg.Head.MsgId, CsMsgResult.NoError, msg);
|
||||
|
||||
//再判断是否有注册的指定消息
|
||||
if (_aMsgHandles[hashIndex] != null &&
|
||||
_adwMsgRegSeq[hashIndex] == dwSeq &&
|
||||
_aiMsgRegResCmdID[hashIndex] == (int)msg.Head.MsgId)
|
||||
{
|
||||
OnCallSeqHandle(_adwMsgRegSeq[hashIndex], _aiMsgRegResCmdID[hashIndex]);
|
||||
_aMsgHandles[hashIndex](CsMsgResult.NoError, msg);
|
||||
RmvReg((int)hashIndex);
|
||||
bHaveHandle = true;
|
||||
}
|
||||
|
||||
if (!bHaveHandle)
|
||||
{
|
||||
Log.Debug("there is no handle for Msg[{0}]", msg.Head.MsgId);
|
||||
}
|
||||
}
|
||||
|
||||
private float NowTime => GameTime.unscaledTime;
|
||||
|
||||
public void Update()
|
||||
{
|
||||
CheckTimeOut();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定时检查是否请求超时。
|
||||
/// </summary>
|
||||
private void CheckTimeOut()
|
||||
{
|
||||
float timeout = _timeout;
|
||||
float nowTime = NowTime;
|
||||
for (int i = 0; i < CheckTimeoutPerframe; i++)
|
||||
{
|
||||
_dwLastCheckIndex = (_dwLastCheckIndex + 1) % MaxMsgHandle;
|
||||
if (_aMsgHandles[_dwLastCheckIndex] != null)
|
||||
{
|
||||
if (_fMsgRegTime[_dwLastCheckIndex] + timeout < nowTime)
|
||||
{
|
||||
Log.Error("msg timeout, resCmdID[{0}], reqSeq[{1}]", _aiMsgRegResCmdID[_dwLastCheckIndex],
|
||||
_adwMsgRegSeq[_dwLastCheckIndex]);
|
||||
|
||||
OnCallSeqHandle(_adwMsgRegSeq[_dwLastCheckIndex], _aiMsgRegResCmdID[_dwLastCheckIndex]);
|
||||
NotifyTimeout(_aMsgHandles[_dwLastCheckIndex]);
|
||||
|
||||
RmvReg((int)_dwLastCheckIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RmvReg(int index)
|
||||
{
|
||||
_aMsgHandles[index] = null;
|
||||
_adwMsgRegSeq[index] = 0;
|
||||
_aiMsgRegResCmdID[index] = 0;
|
||||
_fMsgRegTime[index] = 0;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d667fb84fed4c5f93a06c464585512f
|
||||
timeCreated: 1684333223
|
@@ -1,226 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using GameProto;
|
||||
using Google.Protobuf;
|
||||
using TEngine;
|
||||
|
||||
namespace GameLogic
|
||||
{
|
||||
public class NetworkChannelHelper : INetworkChannelHelper, IMemory
|
||||
{
|
||||
private readonly Dictionary<int, Type> _serverToClientPacketTypes = new Dictionary<int, Type>();
|
||||
private readonly MemoryStream _cachedStream = new MemoryStream(1024 * 8);
|
||||
private INetworkChannel _networkChannel = null;
|
||||
|
||||
/// <summary>
|
||||
/// 获取消息包头长度。
|
||||
/// <remarks>4。</remarks>
|
||||
/// </summary>
|
||||
public int PacketHeaderLength => sizeof(int);
|
||||
|
||||
/// <summary>
|
||||
/// 初始化网络频道辅助器。
|
||||
/// </summary>
|
||||
/// <param name="networkChannel">网络频道。</param>
|
||||
public void Initialize(INetworkChannel networkChannel)
|
||||
{
|
||||
_networkChannel = networkChannel;
|
||||
|
||||
GameEvent.AddEventListener<INetworkChannel, object>(NetworkEvent.NetworkConnectedEvent, OnNetworkConnected);
|
||||
GameEvent.AddEventListener<INetworkChannel>(NetworkEvent.NetworkClosedEvent, OnNetworkClosed);
|
||||
GameEvent.AddEventListener<INetworkChannel, int>(NetworkEvent.NetworkMissHeartBeatEvent, OnNetworkMissHeartBeat);
|
||||
GameEvent.AddEventListener<INetworkChannel, NetworkErrorCode, SocketError, string>(NetworkEvent.NetworkErrorEvent, OnNetworkError);
|
||||
GameEvent.AddEventListener<INetworkChannel, object>(NetworkEvent.NetworkCustomErrorEvent, OnNetworkCustomError);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭并清理网络频道辅助器。
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
GameEvent.RemoveEventListener<INetworkChannel, object>(NetworkEvent.NetworkConnectedEvent, OnNetworkConnected);
|
||||
GameEvent.RemoveEventListener<INetworkChannel>(NetworkEvent.NetworkClosedEvent, OnNetworkClosed);
|
||||
GameEvent.RemoveEventListener<INetworkChannel, int>(NetworkEvent.NetworkMissHeartBeatEvent, OnNetworkMissHeartBeat);
|
||||
GameEvent.RemoveEventListener<INetworkChannel, NetworkErrorCode, SocketError, string>(NetworkEvent.NetworkErrorEvent, OnNetworkError);
|
||||
GameEvent.RemoveEventListener<INetworkChannel, object>(NetworkEvent.NetworkCustomErrorEvent, OnNetworkCustomError);
|
||||
|
||||
_networkChannel = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 准备进行连接。
|
||||
/// </summary>
|
||||
public void PrepareForConnecting()
|
||||
{
|
||||
_networkChannel.Socket.ReceiveBufferSize = 1024 * 64;
|
||||
_networkChannel.Socket.SendBufferSize = 1024 * 64;
|
||||
}
|
||||
|
||||
public CSPkg HeartBeatPack = new CSPkg { Head = new CSPkgHead(), Body = new CSPkgBody() };
|
||||
|
||||
/// <summary>
|
||||
/// 发送心跳消息包。
|
||||
/// </summary>
|
||||
/// <returns>是否发送心跳消息包成功。</returns>
|
||||
public bool SendHeartBeat()
|
||||
{
|
||||
HeartBeatPack.Head.MsgId = (uint)CSMsgID.CsCmdHeatbeatReq;
|
||||
_networkChannel.Send(HeartBeatPack);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 序列化消息包。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">消息包类型。</typeparam>
|
||||
/// <param name="packet">要序列化的消息包。</param>
|
||||
/// <param name="destination">要序列化的目标流。</param>
|
||||
/// <returns>是否序列化成功。</returns>
|
||||
public bool Serialize(CSPkg packet, Stream destination)
|
||||
{
|
||||
if (packet == null)
|
||||
{
|
||||
Log.Warning("Packet is invalid.");
|
||||
return false;
|
||||
}
|
||||
|
||||
_cachedStream.SetLength(_cachedStream.Capacity); // 此行防止 Array.Copy 的数据无法写入
|
||||
_cachedStream.Position = 0L;
|
||||
global::ProtobufUtility.ToStreamWithHead(packet,_cachedStream);
|
||||
_cachedStream.WriteTo(destination);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化消息包头。
|
||||
/// </summary>
|
||||
/// <param name="source">要反序列化的来源流。</param>
|
||||
/// <param name="customErrorData">用户自定义错误数据。</param>
|
||||
/// <returns>反序列化后的消息包头。</returns>
|
||||
public IPacketHeader DeserializePacketHeader(Stream source, out object customErrorData)
|
||||
{
|
||||
// 注意:此函数并不在主线程调用!
|
||||
customErrorData = null;
|
||||
PacketHeader packetHeader = MemoryPool.Acquire<PacketHeader>();
|
||||
packetHeader.PacketLength = ((MemoryStream)source).GetBuffer()[0];
|
||||
return packetHeader;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化消息包。
|
||||
/// </summary>
|
||||
/// <param name="packetHeader">消息包头。</param>
|
||||
/// <param name="source">要反序列化的来源流。</param>
|
||||
/// <param name="customErrorData">用户自定义错误数据。</param>
|
||||
/// <returns>反序列化后的消息包。</returns>
|
||||
public CSPkg DeserializePacket(IPacketHeader packetHeader, Stream source, out object customErrorData)
|
||||
{
|
||||
// 注意:此函数并不在主线程调用!
|
||||
customErrorData = null;
|
||||
|
||||
PacketHeader scPacketHeader = packetHeader as PacketHeader;
|
||||
if (scPacketHeader == null)
|
||||
{
|
||||
Log.Warning("Packet header is invalid.");
|
||||
return null;
|
||||
}
|
||||
|
||||
CSPkg csPkg = null;
|
||||
if (scPacketHeader.IsValid)
|
||||
{
|
||||
try
|
||||
{
|
||||
csPkg = global::ProtobufUtility.Deserialize(((MemoryStream)source).GetBuffer(),0,scPacketHeader.PacketLength);
|
||||
Log.Debug("[s-c] CmdId[{0}]\n{1}", csPkg.Head.MsgId, csPkg.ToString());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Warning(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Warning("Packet header is invalid.");
|
||||
}
|
||||
|
||||
MemoryPool.Release(scPacketHeader);
|
||||
return csPkg;
|
||||
}
|
||||
|
||||
private Type GetServerToClientPacketType(int id)
|
||||
{
|
||||
if (_serverToClientPacketTypes.TryGetValue(id, out var type))
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void OnNetworkConnected(INetworkChannel channel, object userdata)
|
||||
{
|
||||
if (channel != _networkChannel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Info("Network channel '{0}' connected, local address '{1}', remote address '{2}'.",
|
||||
channel.Name, channel.Socket.LocalEndPoint.ToString(),
|
||||
channel.Socket.RemoteEndPoint.ToString());
|
||||
}
|
||||
|
||||
private void OnNetworkClosed(INetworkChannel channel)
|
||||
{
|
||||
if (channel != _networkChannel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Info("Network channel '{0}' closed.", channel.Name);
|
||||
}
|
||||
|
||||
private void OnNetworkMissHeartBeat(INetworkChannel channel, int missCount)
|
||||
{
|
||||
if (channel != _networkChannel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Fatal("Network channel '{0}' miss heart beat '{1}' times.", channel.Name, missCount.ToString());
|
||||
|
||||
if (missCount < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
channel.Close();
|
||||
}
|
||||
|
||||
private void OnNetworkError(INetworkChannel channel, NetworkErrorCode networkErrorCode, SocketError socketError, string errorMessage)
|
||||
{
|
||||
if (channel != _networkChannel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Fatal("Network channel '{0}' error, error code is '{1}', error message is '{2}'.", channel.Name, networkErrorCode.ToString(), errorMessage);
|
||||
|
||||
channel.Close();
|
||||
}
|
||||
|
||||
private void OnNetworkCustomError(INetworkChannel channel, object userData)
|
||||
{
|
||||
if (channel != _networkChannel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf86ce2ddfb5429abecfb06257c86acd
|
||||
timeCreated: 1682045961
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e77590d750cf480baae2468038654bc0
|
||||
timeCreated: 1681991042
|
@@ -1,23 +0,0 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 网络地址类型。
|
||||
/// </summary>
|
||||
public enum AddressFamily : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// 未知。
|
||||
/// </summary>
|
||||
Unknown = 0,
|
||||
|
||||
/// <summary>
|
||||
/// IP 版本 4。
|
||||
/// </summary>
|
||||
IPv4,
|
||||
|
||||
/// <summary>
|
||||
/// IP 版本 6。
|
||||
/// </summary>
|
||||
IPv6
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd8e805430d24bdb8c2679b59ba7c2d6
|
||||
timeCreated: 1681993653
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9aefe7f3e0fd485091a20579b29872a7
|
||||
timeCreated: 1681994393
|
@@ -1,180 +0,0 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using GameProto;
|
||||
using Google.Protobuf;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 网络频道接口。
|
||||
/// </summary>
|
||||
public interface INetworkChannel
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取网络频道名称。
|
||||
/// </summary>
|
||||
string Name
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取网络频道所使用的 Socket。
|
||||
/// </summary>
|
||||
Socket Socket
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取是否已连接。
|
||||
/// </summary>
|
||||
bool Connected
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取网络服务类型。
|
||||
/// </summary>
|
||||
ServiceType ServiceType
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取网络地址类型。
|
||||
/// </summary>
|
||||
AddressFamily AddressFamily
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取要发送的消息包数量。
|
||||
/// </summary>
|
||||
int SendPacketCount
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取累计发送的消息包数量。
|
||||
/// </summary>
|
||||
int SentPacketCount
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取已接收未处理的消息包数量。
|
||||
/// </summary>
|
||||
int ReceivePacketCount
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取累计已接收的消息包数量。
|
||||
/// </summary>
|
||||
int ReceivedPacketCount
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置当收到消息包时是否重置心跳流逝时间。
|
||||
/// </summary>
|
||||
bool ResetHeartBeatElapseSecondsWhenReceivePacket
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取丢失心跳的次数。
|
||||
/// </summary>
|
||||
int MissHeartBeatCount
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置心跳间隔时长,以秒为单位。
|
||||
/// </summary>
|
||||
float HeartBeatInterval
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取心跳等待时长,以秒为单位。
|
||||
/// </summary>
|
||||
float HeartBeatElapseSeconds
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册网络消息包处理函数。
|
||||
/// </summary>
|
||||
/// <param name="msgId">网络消息包id。</param>
|
||||
/// <param name="msgDelegate">要注册的网络消息包处理函数。</param>
|
||||
/// <param name="checkRepeat">是否检测重复。</param>
|
||||
void RegisterMsgHandler(int msgId, CsMsgDelegate msgDelegate, bool checkRepeat = false);
|
||||
|
||||
/// <summary>
|
||||
/// 移除网络消息包处理函数。
|
||||
/// </summary>
|
||||
/// <param name="msgId">网络消息包id。</param>
|
||||
/// <param name="msgDelegate">要注册的网络消息包处理函数。</param>
|
||||
void RemoveMsgHandler(int msgId, CsMsgDelegate msgDelegate);
|
||||
|
||||
/// <summary>
|
||||
/// 连接到远程主机。
|
||||
/// </summary>
|
||||
/// <param name="ipAddress">远程主机的 IP 地址。</param>
|
||||
/// <param name="port">远程主机的端口号。</param>
|
||||
void Connect(string ipAddress, int port);
|
||||
|
||||
/// <summary>
|
||||
/// 连接到远程主机。
|
||||
/// </summary>
|
||||
/// <param name="ipAddress">远程主机的 IP 地址。</param>
|
||||
/// <param name="port">远程主机的端口号。</param>
|
||||
void Connect(IPAddress ipAddress, int port);
|
||||
|
||||
/// <summary>
|
||||
/// 连接到远程主机。
|
||||
/// </summary>
|
||||
/// <param name="ipAddress">远程主机的 IP 地址。</param>
|
||||
/// <param name="port">远程主机的端口号。</param>
|
||||
/// <param name="userData">用户自定义数据。</param>
|
||||
void Connect(IPAddress ipAddress, int port, object userData);
|
||||
|
||||
/// <summary>
|
||||
/// 关闭网络频道。
|
||||
/// </summary>
|
||||
void Close();
|
||||
|
||||
/// <summary>
|
||||
/// 向远程主机发送消息包。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">消息包类型。</typeparam>
|
||||
/// <param name="packet">要发送的消息包。</param>
|
||||
/// <returns>消息包是否发送成功。</returns>
|
||||
bool Send(CSPkg packet);
|
||||
|
||||
/// <summary>
|
||||
/// 向远程主机发送消息包并注册消息回调。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">消息包类型。</typeparam>
|
||||
/// <param name="packet">要发送的消息包。</param>
|
||||
/// <param name="resHandler">要注册的回调。</param>
|
||||
/// <param name="needShowWaitUI">是否需要等待UI。</param>
|
||||
/// <returns>消息包是否发送成功。</returns>
|
||||
bool Send(CSPkg packet, CsMsgDelegate resHandler, bool needShowWaitUI = false);
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 09b554ed41c546a1bc40e5be392f836a
|
||||
timeCreated: 1681993830
|
@@ -1,67 +0,0 @@
|
||||
using System.IO;
|
||||
using GameProto;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 网络频道辅助器接口。
|
||||
/// </summary>
|
||||
public interface INetworkChannelHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取消息包头长度。
|
||||
/// </summary>
|
||||
int PacketHeaderLength
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化网络频道辅助器。
|
||||
/// </summary>
|
||||
/// <param name="networkChannel">网络频道。</param>
|
||||
void Initialize(INetworkChannel networkChannel);
|
||||
|
||||
/// <summary>
|
||||
/// 关闭并清理网络频道辅助器。
|
||||
/// </summary>
|
||||
void Shutdown();
|
||||
|
||||
/// <summary>
|
||||
/// 准备进行连接。
|
||||
/// </summary>
|
||||
void PrepareForConnecting();
|
||||
|
||||
/// <summary>
|
||||
/// 发送心跳消息包。
|
||||
/// </summary>
|
||||
/// <returns>是否发送心跳消息包成功。</returns>
|
||||
bool SendHeartBeat();
|
||||
|
||||
/// <summary>
|
||||
/// 序列化消息包。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">消息包类型。</typeparam>
|
||||
/// <param name="packet">要序列化的消息包。</param>
|
||||
/// <param name="destination">要序列化的目标流。</param>
|
||||
/// <returns>是否序列化成功。</returns>
|
||||
bool Serialize(CSPkg packet, Stream destination);
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化消息包头。
|
||||
/// </summary>
|
||||
/// <param name="source">要反序列化的来源流。</param>
|
||||
/// <param name="customErrorData">用户自定义错误数据。</param>
|
||||
/// <returns>反序列化后的消息包头。</returns>
|
||||
IPacketHeader DeserializePacketHeader(Stream source, out object customErrorData);
|
||||
|
||||
/// <summary>
|
||||
/// 反序列化消息包。
|
||||
/// </summary>
|
||||
/// <param name="packetHeader">消息包头。</param>
|
||||
/// <param name="source">要反序列化的来源流。</param>
|
||||
/// <param name="customErrorData">用户自定义错误数据。</param>
|
||||
/// <returns>反序列化后的消息包。</returns>
|
||||
CSPkg DeserializePacket(IPacketHeader packetHeader, Stream source, out object customErrorData);
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f847791db5a4e6cbbc39dd56a6888d9
|
||||
timeCreated: 1681993713
|
@@ -1,84 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 网络管理器接口。
|
||||
/// </summary>
|
||||
public interface INetworkManager
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取网络频道数量。
|
||||
/// </summary>
|
||||
int NetworkChannelCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 网络连接成功事件。
|
||||
/// </summary>
|
||||
event Action<INetworkChannel, object> NetworkConnected;
|
||||
|
||||
/// <summary>
|
||||
/// 网络连接关闭事件。
|
||||
/// </summary>
|
||||
event Action<INetworkChannel> NetworkClosed;
|
||||
|
||||
/// <summary>
|
||||
/// 网络心跳包丢失事件。
|
||||
/// </summary>
|
||||
event Action<INetworkChannel, int> NetworkMissHeartBeat;
|
||||
|
||||
/// <summary>
|
||||
/// 网络错误事件。
|
||||
/// </summary>
|
||||
event Action<INetworkChannel, NetworkErrorCode, SocketError, string> NetworkError;
|
||||
|
||||
/// <summary>
|
||||
/// 用户自定义网络错误事件。
|
||||
/// </summary>
|
||||
event Action<INetworkChannel, object> NetworkCustomError;
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否存在网络频道。
|
||||
/// </summary>
|
||||
/// <param name="name">网络频道名称。</param>
|
||||
/// <returns>是否存在网络频道。</returns>
|
||||
bool HasNetworkChannel(string name);
|
||||
|
||||
/// <summary>
|
||||
/// 获取网络频道。
|
||||
/// </summary>
|
||||
/// <param name="name">网络频道名称。</param>
|
||||
/// <returns>要获取的网络频道。</returns>
|
||||
INetworkChannel GetNetworkChannel(string name);
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有网络频道。
|
||||
/// </summary>
|
||||
/// <returns>所有网络频道。</returns>
|
||||
INetworkChannel[] GetAllNetworkChannels();
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有网络频道。
|
||||
/// </summary>
|
||||
/// <param name="results">所有网络频道。</param>
|
||||
void GetAllNetworkChannels(List<INetworkChannel> results);
|
||||
|
||||
/// <summary>
|
||||
/// 创建网络频道。
|
||||
/// </summary>
|
||||
/// <param name="name">网络频道名称。</param>
|
||||
/// <param name="serviceType">网络服务类型。</param>
|
||||
/// <param name="networkChannelHelper">网络频道辅助器。</param>
|
||||
/// <returns>要创建的网络频道。</returns>
|
||||
INetworkChannel CreateNetworkChannel(string name, ServiceType serviceType, INetworkChannelHelper networkChannelHelper);
|
||||
|
||||
/// <summary>
|
||||
/// 销毁网络频道。
|
||||
/// </summary>
|
||||
/// <param name="name">网络频道名称。</param>
|
||||
/// <returns>是否销毁网络频道成功。</returns>
|
||||
bool DestroyNetworkChannel(string name);
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7de8458fc50e4cd3b49ef73d35ad9763
|
||||
timeCreated: 1681993806
|
@@ -1,16 +0,0 @@
|
||||
namespace TEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 网络消息包头接口。
|
||||
/// </summary>
|
||||
public interface IPacketHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取网络消息包长度。
|
||||
/// </summary>
|
||||
int PacketLength
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7659e4a617d84126b0a548077fb4fdcc
|
||||
timeCreated: 1681994226
|
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d988d26345f402f9177488d8921184f
|
||||
timeCreated: 1682092063
|
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6dff8f4f5dd94df49bf6d616fb11cc9c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,71 +0,0 @@
|
||||
using System.Buffers;
|
||||
using Cysharp.Threading.Tasks;
|
||||
|
||||
namespace System.Net.Sockets.Kcp
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于调试的KCP IO 类,没有Kcp功能
|
||||
/// </summary>
|
||||
public class FakeKcpIO : IKcpIO
|
||||
{
|
||||
QueuePipe<byte[]> recv = new QueuePipe<byte[]>();
|
||||
public int Input(ReadOnlySpan<byte> span)
|
||||
{
|
||||
byte[] buffer = new byte[span.Length];
|
||||
span.CopyTo(buffer);
|
||||
recv.Write(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int Input(ReadOnlySequence<byte> span)
|
||||
{
|
||||
byte[] buffer = new byte[span.Length];
|
||||
span.CopyTo(buffer);
|
||||
return Input(buffer);
|
||||
}
|
||||
|
||||
public async UniTask RecvAsync(IBufferWriter<byte> writer, object options = null)
|
||||
{
|
||||
var buffer = await recv.ReadAsync().ConfigureAwait(false);
|
||||
var target = writer.GetMemory(buffer.Length);
|
||||
buffer.AsSpan().CopyTo(target.Span);
|
||||
writer.Advance(buffer.Length);
|
||||
}
|
||||
|
||||
public async UniTask<int> RecvAsync(ArraySegment<byte> buffer, object options = null)
|
||||
{
|
||||
var temp = await recv.ReadAsync().ConfigureAwait(false);
|
||||
temp.AsSpan().CopyTo(buffer);
|
||||
return temp.Length;
|
||||
}
|
||||
|
||||
QueuePipe<byte[]> send = new QueuePipe<byte[]>();
|
||||
public int Send(ReadOnlySpan<byte> span, object options = null)
|
||||
{
|
||||
byte[] buffer = new byte[span.Length];
|
||||
span.CopyTo(buffer);
|
||||
send.Write(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int Send(ReadOnlySequence<byte> span, object options = null)
|
||||
{
|
||||
byte[] buffer = new byte[span.Length];
|
||||
span.CopyTo(buffer);
|
||||
return Send(buffer);
|
||||
}
|
||||
|
||||
public async UniTask OutputAsync(IBufferWriter<byte> writer, object options = null)
|
||||
{
|
||||
var buffer = await send.ReadAsync().ConfigureAwait(false);
|
||||
Write(writer, buffer);
|
||||
}
|
||||
|
||||
private static void Write(IBufferWriter<byte> writer, byte[] buffer)
|
||||
{
|
||||
var span = writer.GetSpan(buffer.Length);
|
||||
buffer.AsSpan().CopyTo(span);
|
||||
writer.Advance(buffer.Length);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3c2f9de3c34ffc409549b86ac3fc530
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,147 +0,0 @@
|
||||
using BufferOwner = System.Buffers.IMemoryOwner<byte>;
|
||||
using System.Buffers;
|
||||
using Cysharp.Threading.Tasks;
|
||||
|
||||
namespace System.Net.Sockets.Kcp
|
||||
{
|
||||
/// <summary>
|
||||
/// Kcp回调
|
||||
/// </summary>
|
||||
public interface IKcpCallback
|
||||
{
|
||||
/// <summary>
|
||||
/// kcp 发送方向输出
|
||||
/// </summary>
|
||||
/// <param name="buffer">kcp 交出发送缓冲区控制权,缓冲区来自<see cref="RentBuffer(int)"/></param>
|
||||
/// <param name="avalidLength">数据的有效长度</param>
|
||||
/// <returns>不需要返回值</returns>
|
||||
/// <remarks>通过增加 avalidLength 能够在协议栈中有效的减少数据拷贝</remarks>
|
||||
void Output(BufferOwner buffer, int avalidLength);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Kcp回调
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 失败设计,<see cref="KcpOutputWriter.Output(BufferOwner, int)"/>。IMemoryOwner是没有办法代替的。
|
||||
/// 这里只相当于把 IKcpCallback 和 IRentable 和并。
|
||||
/// </remarks>
|
||||
public interface IKcpOutputWriter : IBufferWriter<byte>
|
||||
{
|
||||
int UnflushedBytes { get; }
|
||||
void Flush();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 外部提供缓冲区,可以在外部链接一个内存池
|
||||
/// </summary>
|
||||
public interface IRentable
|
||||
{
|
||||
/// <summary>
|
||||
/// 外部提供缓冲区,可以在外部链接一个内存池
|
||||
/// </summary>
|
||||
BufferOwner RentBuffer(int length);
|
||||
}
|
||||
|
||||
public interface IKcpSetting
|
||||
{
|
||||
int Interval(int interval);
|
||||
/// <summary>
|
||||
/// fastest: ikcp_nodelay(kcp, 1, 20, 2, 1)
|
||||
/// </summary>
|
||||
/// <param name="nodelay">0:disable(default), 1:enable</param>
|
||||
/// <param name="interval">internal update timer interval in millisec, default is 100ms</param>
|
||||
/// <param name="resend">0:disable fast resend(default), 1:enable fast resend</param>
|
||||
/// <param name="nc">0:normal congestion control(default), 1:disable congestion control</param>
|
||||
/// <returns></returns>
|
||||
int NoDelay(int nodelay, int interval, int resend, int nc);
|
||||
/// <summary>
|
||||
/// change MTU size, default is 1400
|
||||
/// <para>** 这个方法不是线程安全的。请在没有发送和接收时调用 。</para>
|
||||
/// </summary>
|
||||
/// <param name="mtu"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// 如果没有必要,不要修改Mtu。过小的Mtu会导致分片数大于接收窗口,造成kcp阻塞冻结。
|
||||
/// </remarks>
|
||||
int SetMtu(int mtu = 1400);
|
||||
/// <summary>
|
||||
/// set maximum window size: sndwnd=32, rcvwnd=128 by default
|
||||
/// </summary>
|
||||
/// <param name="sndwnd"></param>
|
||||
/// <param name="rcvwnd"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// 如果没有必要请不要修改。注意确保接收窗口必须大于最大分片数。
|
||||
/// </remarks>
|
||||
int WndSize(int sndwnd = 32, int rcvwnd = 128);
|
||||
}
|
||||
|
||||
public interface IKcpUpdate
|
||||
{
|
||||
void Update(in DateTimeOffset time);
|
||||
}
|
||||
|
||||
public interface IKcpSendable
|
||||
{
|
||||
/// <summary>
|
||||
/// 将要发送到网络的数据Send到kcp协议中
|
||||
/// </summary>
|
||||
/// <param name="span"></param>
|
||||
/// <param name="options"></param>
|
||||
int Send(ReadOnlySpan<byte> span, object options = null);
|
||||
/// <summary>
|
||||
/// 将要发送到网络的数据Send到kcp协议中
|
||||
/// </summary>
|
||||
/// <param name="span"></param>
|
||||
/// <param name="options"></param>
|
||||
int Send(ReadOnlySequence<byte> span, object options = null);
|
||||
}
|
||||
|
||||
public interface IKcpInputable
|
||||
{
|
||||
/// <summary>
|
||||
/// 下层收到数据后添加到kcp协议中
|
||||
/// </summary>
|
||||
/// <param name="span"></param>
|
||||
int Input(ReadOnlySpan<byte> span);
|
||||
/// <summary>
|
||||
/// 下层收到数据后添加到kcp协议中
|
||||
/// </summary>
|
||||
/// <param name="span"></param>
|
||||
int Input(ReadOnlySequence<byte> span);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// kcp协议输入输出标准接口
|
||||
/// </summary>
|
||||
public interface IKcpIO : IKcpSendable, IKcpInputable
|
||||
{
|
||||
/// <summary>
|
||||
/// 从kcp中取出一个整合完毕的数据包
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
UniTask RecvAsync(IBufferWriter<byte> writer, object options = null);
|
||||
|
||||
/// <summary>
|
||||
/// 从kcp中取出一个整合完毕的数据包
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <returns>接收数据长度</returns>
|
||||
UniTask<int> RecvAsync(ArraySegment<byte> buffer, object options = null);
|
||||
|
||||
/// <summary>
|
||||
/// 从kcp协议中取出需要发送到网络的数据。
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <returns></returns>
|
||||
UniTask OutputAsync(IBufferWriter<byte> writer, object options = null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0ca98e42147b3948bc8d30f24e9c366
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,88 +0,0 @@
|
||||
namespace System.Net.Sockets.Kcp
|
||||
{
|
||||
/// <summary>
|
||||
/// Kcp报头
|
||||
/// https://zhuanlan.zhihu.com/p/559191428
|
||||
/// </summary>
|
||||
public interface IKcpHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// 会话编号,两方一致才会通信
|
||||
/// </summary>
|
||||
uint conv { get; set; }
|
||||
/// <summary>
|
||||
/// 指令类型
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para/> IKCP_CMD_PUSH = 81 // cmd: push data 数据报文
|
||||
/// <para/> IKCP_CMD_ACK = 82 // cmd: ack 确认报文
|
||||
/// <para/> IKCP_CMD_WASK = 83 // cmd: window probe (ask) 窗口探测报文,询问对端剩余接收窗口的大小.
|
||||
/// <para/> IKCP_CMD_WINS = 84 // cmd: window size (tell) 窗口通知报文,通知对端剩余接收窗口的大小.
|
||||
/// </remarks>
|
||||
byte cmd { get; set; }
|
||||
/// <summary>
|
||||
/// 剩余分片数量,表示随后还有多少个报文属于同一个包。
|
||||
/// </summary>
|
||||
byte frg { get; set; }
|
||||
/// <summary>
|
||||
/// 自己可用窗口大小
|
||||
/// </summary>
|
||||
ushort wnd { get; set; }
|
||||
/// <summary>
|
||||
/// 发送时的时间戳 <seealso cref="DateTimeOffset.ToUnixTimeMilliseconds"/>
|
||||
/// </summary>
|
||||
uint ts { get; set; }
|
||||
/// <summary>
|
||||
/// 编号 确认编号或者报文编号
|
||||
/// </summary>
|
||||
uint sn { get; set; }
|
||||
/// <summary>
|
||||
/// 代表编号前面的所有报都收到了的标志
|
||||
/// </summary>
|
||||
uint una { get; set; }
|
||||
/// <summary>
|
||||
/// 数据内容长度
|
||||
/// </summary>
|
||||
uint len { get; }
|
||||
}
|
||||
public interface IKcpSegment : IKcpHeader
|
||||
{
|
||||
/// <summary>
|
||||
/// 重传的时间戳。超过当前时间重发这个包
|
||||
/// </summary>
|
||||
uint resendts { get; set; }
|
||||
/// <summary>
|
||||
/// 超时重传时间,根据网络去定
|
||||
/// </summary>
|
||||
uint rto { get; set; }
|
||||
/// <summary>
|
||||
/// 快速重传机制,记录被跳过的次数,超过次数进行快速重传
|
||||
/// </summary>
|
||||
uint fastack { get; set; }
|
||||
/// <summary>
|
||||
/// 重传次数
|
||||
/// </summary>
|
||||
uint xmit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据内容
|
||||
/// </summary>
|
||||
Span<byte> data { get; }
|
||||
/// <summary>
|
||||
/// 将IKcpSegment编码成字节数组,并返回总长度(包括Kcp报头)
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <returns></returns>
|
||||
int Encode(Span<byte> buffer);
|
||||
}
|
||||
|
||||
public interface ISegmentManager<Segment> where Segment : IKcpSegment
|
||||
{
|
||||
Segment Alloc(int appendDateSize);
|
||||
void Free(Segment seg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9259bb6b548e46459cc766d8fe2faeb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,387 +0,0 @@
|
||||
using System.Buffers;
|
||||
using BufferOwner = System.Buffers.IMemoryOwner<byte>;
|
||||
|
||||
namespace System.Net.Sockets.Kcp
|
||||
{
|
||||
public class Kcp<Segment> : KcpCore<Segment>
|
||||
where Segment : IKcpSegment
|
||||
{
|
||||
/// <summary>
|
||||
/// create a new kcp control object, 'conv' must equal in two endpoint
|
||||
/// from the same connection.
|
||||
/// </summary>
|
||||
/// <param name="conv_"></param>
|
||||
/// <param name="callback"></param>
|
||||
/// <param name="rentable">可租用内存的回调</param>
|
||||
public Kcp(uint conv_, IKcpCallback callback, IRentable rentable = null)
|
||||
: base(conv_)
|
||||
{
|
||||
callbackHandle = callback;
|
||||
this.rentable = rentable;
|
||||
}
|
||||
|
||||
|
||||
//extension 重构和新增加的部分============================================
|
||||
|
||||
IRentable rentable;
|
||||
/// <summary>
|
||||
/// 如果外部能够提供缓冲区则使用外部缓冲区,否则new byte[]
|
||||
/// </summary>
|
||||
/// <param name="needSize"></param>
|
||||
/// <returns></returns>
|
||||
internal protected override BufferOwner CreateBuffer(int needSize)
|
||||
{
|
||||
var res = rentable?.RentBuffer(needSize);
|
||||
if (res == null)
|
||||
{
|
||||
return base.CreateBuffer(needSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (res.Memory.Length < needSize)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(rentable.RentBuffer)} 指定的委托不符合标准,返回的" +
|
||||
$"BufferOwner.Memory.Length 小于 {nameof(needSize)}");
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryRecv Recv设计上同一时刻只允许一个线程调用。
|
||||
/// <para/>因为要保证数据顺序,多个线程同时调用Recv也没有意义。
|
||||
/// <para/>所以只需要部分加锁即可。
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public (BufferOwner buffer, int avalidLength) TryRecv()
|
||||
{
|
||||
var peekSize = -1;
|
||||
lock (rcv_queueLock)
|
||||
{
|
||||
if (rcv_queue.Count == 0)
|
||||
{
|
||||
///没有可用包
|
||||
return (null, -1);
|
||||
}
|
||||
|
||||
var seq = rcv_queue[0];
|
||||
|
||||
if (seq.frg == 0)
|
||||
{
|
||||
peekSize = (int)seq.len;
|
||||
}
|
||||
|
||||
if (rcv_queue.Count < seq.frg + 1)
|
||||
{
|
||||
///没有足够的包
|
||||
return (null, -1);
|
||||
}
|
||||
|
||||
uint length = 0;
|
||||
|
||||
foreach (var item in rcv_queue)
|
||||
{
|
||||
length += item.len;
|
||||
if (item.frg == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
peekSize = (int)length;
|
||||
|
||||
if (peekSize <= 0)
|
||||
{
|
||||
return (null, -2);
|
||||
}
|
||||
}
|
||||
|
||||
var buffer = CreateBuffer(peekSize);
|
||||
var recvlength = UncheckRecv(buffer.Memory.Span);
|
||||
return (buffer, recvlength);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TryRecv Recv设计上同一时刻只允许一个线程调用。
|
||||
/// <para/>因为要保证数据顺序,多个线程同时调用Recv也没有意义。
|
||||
/// <para/>所以只需要部分加锁即可。
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <returns></returns>
|
||||
public int TryRecv(IBufferWriter<byte> writer)
|
||||
{
|
||||
var peekSize = -1;
|
||||
lock (rcv_queueLock)
|
||||
{
|
||||
if (rcv_queue.Count == 0)
|
||||
{
|
||||
///没有可用包
|
||||
return -1;
|
||||
}
|
||||
|
||||
var seq = rcv_queue[0];
|
||||
|
||||
if (seq.frg == 0)
|
||||
{
|
||||
peekSize = (int)seq.len;
|
||||
}
|
||||
|
||||
if (rcv_queue.Count < seq.frg + 1)
|
||||
{
|
||||
///没有足够的包
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint length = 0;
|
||||
|
||||
foreach (var item in rcv_queue)
|
||||
{
|
||||
length += item.len;
|
||||
if (item.frg == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
peekSize = (int)length;
|
||||
|
||||
if (peekSize <= 0)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
return UncheckRecv(writer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// user/upper level recv: returns size, returns below zero for EAGAIN
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <returns></returns>
|
||||
public int Recv(Span<byte> buffer)
|
||||
{
|
||||
if (0 == rcv_queue.Count)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
var peekSize = PeekSize();
|
||||
if (peekSize < 0)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (peekSize > buffer.Length)
|
||||
{
|
||||
return -3;
|
||||
}
|
||||
|
||||
/// 拆分函数
|
||||
var recvLength = UncheckRecv(buffer);
|
||||
|
||||
return recvLength;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// user/upper level recv: returns size, returns below zero for EAGAIN
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <returns></returns>
|
||||
public int Recv(IBufferWriter<byte> writer)
|
||||
{
|
||||
if (0 == rcv_queue.Count)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
var peekSize = PeekSize();
|
||||
if (peekSize < 0)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
//if (peekSize > buffer.Length)
|
||||
//{
|
||||
// return -3;
|
||||
//}
|
||||
|
||||
/// 拆分函数
|
||||
var recvLength = UncheckRecv(writer);
|
||||
|
||||
return recvLength;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 这个函数不检查任何参数
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <returns></returns>
|
||||
int UncheckRecv(Span<byte> buffer)
|
||||
{
|
||||
var recover = false;
|
||||
if (rcv_queue.Count >= rcv_wnd)
|
||||
{
|
||||
recover = true;
|
||||
}
|
||||
|
||||
#region merge fragment.
|
||||
/// merge fragment.
|
||||
|
||||
var recvLength = 0;
|
||||
lock (rcv_queueLock)
|
||||
{
|
||||
var count = 0;
|
||||
foreach (var seg in rcv_queue)
|
||||
{
|
||||
seg.data.CopyTo(buffer.Slice(recvLength));
|
||||
recvLength += (int)seg.len;
|
||||
|
||||
count++;
|
||||
int frg = seg.frg;
|
||||
|
||||
SegmentManager.Free(seg);
|
||||
if (frg == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
rcv_queue.RemoveRange(0, count);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
Move_Rcv_buf_2_Rcv_queue();
|
||||
|
||||
#region fast recover
|
||||
/// fast recover
|
||||
if (rcv_queue.Count < rcv_wnd && recover)
|
||||
{
|
||||
// ready to send back IKCP_CMD_WINS in ikcp_flush
|
||||
// tell remote my window size
|
||||
probe |= IKCP_ASK_TELL;
|
||||
}
|
||||
#endregion
|
||||
return recvLength;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 这个函数不检查任何参数
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <returns></returns>
|
||||
int UncheckRecv(IBufferWriter<byte> writer)
|
||||
{
|
||||
var recover = false;
|
||||
if (rcv_queue.Count >= rcv_wnd)
|
||||
{
|
||||
recover = true;
|
||||
}
|
||||
|
||||
#region merge fragment.
|
||||
/// merge fragment.
|
||||
|
||||
var recvLength = 0;
|
||||
lock (rcv_queueLock)
|
||||
{
|
||||
var count = 0;
|
||||
foreach (var seg in rcv_queue)
|
||||
{
|
||||
var len = (int)seg.len;
|
||||
var destination = writer.GetSpan(len);
|
||||
|
||||
seg.data.CopyTo(destination);
|
||||
writer.Advance(len);
|
||||
|
||||
recvLength += len;
|
||||
|
||||
count++;
|
||||
int frg = seg.frg;
|
||||
|
||||
SegmentManager.Free(seg);
|
||||
if (frg == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
rcv_queue.RemoveRange(0, count);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
Move_Rcv_buf_2_Rcv_queue();
|
||||
|
||||
#region fast recover
|
||||
/// fast recover
|
||||
if (rcv_queue.Count < rcv_wnd && recover)
|
||||
{
|
||||
// ready to send back IKCP_CMD_WINS in ikcp_flush
|
||||
// tell remote my window size
|
||||
probe |= IKCP_ASK_TELL;
|
||||
}
|
||||
#endregion
|
||||
return recvLength;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// check the size of next message in the recv queue
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public int PeekSize()
|
||||
{
|
||||
lock (rcv_queueLock)
|
||||
{
|
||||
if (rcv_queue.Count == 0)
|
||||
{
|
||||
///没有可用包
|
||||
return -1;
|
||||
}
|
||||
|
||||
var seq = rcv_queue[0];
|
||||
|
||||
if (seq.frg == 0)
|
||||
{
|
||||
return (int)seq.len;
|
||||
}
|
||||
|
||||
if (rcv_queue.Count < seq.frg + 1)
|
||||
{
|
||||
///没有足够的包
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint length = 0;
|
||||
|
||||
foreach (var seg in rcv_queue)
|
||||
{
|
||||
length += seg.len;
|
||||
if (seg.frg == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (int)length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3840e90e37f0194bbfafb564ff80d45
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fcc0172c723e55a4389ad2f62b68a3fe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,262 +0,0 @@
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using BufferOwner = System.Buffers.IMemoryOwner<byte>;
|
||||
|
||||
namespace System.Net.Sockets.Kcp
|
||||
{
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="IPipe{T}"/>
|
||||
/// <para></para>这是个简单的实现,更复杂使用微软官方实现<see cref="Channel.CreateBounded{T}(int)"/>
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
internal class QueuePipe<T> : Queue<T>
|
||||
{
|
||||
readonly object _innerLock = new object();
|
||||
private TaskCompletionSource<T> source;
|
||||
|
||||
//线程同步上下文由Task机制保证,无需额外处理
|
||||
//SynchronizationContext callbackContext;
|
||||
//public bool UseSynchronizationContext { get; set; } = true;
|
||||
|
||||
public virtual void Write(T item)
|
||||
{
|
||||
lock (_innerLock)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
Enqueue(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Count > 0)
|
||||
{
|
||||
throw new Exception("内部顺序错误,不应该出现,请联系作者");
|
||||
}
|
||||
|
||||
var next = source;
|
||||
source = null;
|
||||
next.TrySetResult(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public new void Enqueue(T item)
|
||||
{
|
||||
lock (_innerLock)
|
||||
{
|
||||
base.Enqueue(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
lock (_innerLock)
|
||||
{
|
||||
if (Count > 0)
|
||||
{
|
||||
var res = Dequeue();
|
||||
var next = source;
|
||||
source = null;
|
||||
next?.TrySetResult(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Task<T> ReadAsync()
|
||||
{
|
||||
lock (_innerLock)
|
||||
{
|
||||
if (this.Count > 0)
|
||||
{
|
||||
var next = Dequeue();
|
||||
return Task.FromResult(next);
|
||||
}
|
||||
else
|
||||
{
|
||||
source = new TaskCompletionSource<T>();
|
||||
return source.Task;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask<T> ReadValueTaskAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class KcpIO<Segment> : KcpCore<Segment>, IKcpIO
|
||||
where Segment : IKcpSegment
|
||||
{
|
||||
OutputQ outq;
|
||||
|
||||
public KcpIO(uint conv_) : base(conv_)
|
||||
{
|
||||
outq = new OutputQ();
|
||||
callbackHandle = outq;
|
||||
}
|
||||
|
||||
internal override void Parse_data(Segment newseg)
|
||||
{
|
||||
base.Parse_data(newseg);
|
||||
|
||||
lock (rcv_queueLock)
|
||||
{
|
||||
var recover = false;
|
||||
if (rcv_queue.Count >= rcv_wnd)
|
||||
{
|
||||
recover = true;
|
||||
}
|
||||
|
||||
while (TryRecv(out var arraySegment) > 0)
|
||||
{
|
||||
recvSignal.Enqueue(arraySegment);
|
||||
}
|
||||
|
||||
recvSignal.Flush();
|
||||
|
||||
#region fast recover
|
||||
|
||||
/// fast recover
|
||||
if (rcv_queue.Count < rcv_wnd && recover)
|
||||
{
|
||||
// ready to send back IKCP_CMD_WINS in ikcp_flush
|
||||
// tell remote my window size
|
||||
probe |= IKCP_ASK_TELL;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
QueuePipe<ArraySegment<Segment>> recvSignal = new QueuePipe<ArraySegment<Segment>>();
|
||||
|
||||
internal int TryRecv(out ArraySegment<Segment> package)
|
||||
{
|
||||
package = default;
|
||||
lock (rcv_queueLock)
|
||||
{
|
||||
var peekSize = -1;
|
||||
if (rcv_queue.Count == 0)
|
||||
{
|
||||
///没有可用包
|
||||
return -1;
|
||||
}
|
||||
|
||||
var seq = rcv_queue[0];
|
||||
|
||||
if (seq.frg == 0)
|
||||
{
|
||||
peekSize = (int)seq.len;
|
||||
}
|
||||
|
||||
if (rcv_queue.Count < seq.frg + 1)
|
||||
{
|
||||
///没有足够的包
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint length = 0;
|
||||
|
||||
Segment[] kcpSegments = ArrayPool<Segment>.Shared.Rent(seq.frg + 1);
|
||||
|
||||
var index = 0;
|
||||
foreach (var item in rcv_queue)
|
||||
{
|
||||
kcpSegments[index] = item;
|
||||
index++;
|
||||
length += item.len;
|
||||
if (item.frg == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index > 0)
|
||||
{
|
||||
rcv_queue.RemoveRange(0, index);
|
||||
}
|
||||
|
||||
package = new ArraySegment<Segment>(kcpSegments, 0, index);
|
||||
|
||||
peekSize = (int)length;
|
||||
|
||||
if (peekSize <= 0)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
return peekSize;
|
||||
}
|
||||
}
|
||||
|
||||
public async UniTask RecvAsync(IBufferWriter<byte> writer, object options = null)
|
||||
{
|
||||
var arraySegment = await recvSignal.ReadAsync().ConfigureAwait(false);
|
||||
for (int i = arraySegment.Offset; i < arraySegment.Count; i++)
|
||||
{
|
||||
WriteRecv(writer, arraySegment.Array[i]);
|
||||
}
|
||||
|
||||
ArrayPool<Segment>.Shared.Return(arraySegment.Array, true);
|
||||
}
|
||||
|
||||
private void WriteRecv(IBufferWriter<byte> writer, Segment seg)
|
||||
{
|
||||
var curCount = (int)seg.len;
|
||||
var target = writer.GetSpan(curCount);
|
||||
seg.data.CopyTo(target);
|
||||
SegmentManager.Free(seg);
|
||||
writer.Advance(curCount);
|
||||
}
|
||||
|
||||
public async UniTask<int> RecvAsync(ArraySegment<byte> buffer, object options = null)
|
||||
{
|
||||
var arraySegment = await recvSignal.ReadAsync().ConfigureAwait(false);
|
||||
int start = buffer.Offset;
|
||||
for (int i = arraySegment.Offset; i < arraySegment.Count; i++)
|
||||
{
|
||||
var target = new Memory<byte>(buffer.Array, start, buffer.Array.Length - start);
|
||||
|
||||
var seg = arraySegment.Array[i];
|
||||
seg.data.CopyTo(target.Span);
|
||||
start += seg.data.Length;
|
||||
|
||||
SegmentManager.Free(seg);
|
||||
}
|
||||
|
||||
ArrayPool<Segment>.Shared.Return(arraySegment.Array, true);
|
||||
return start - buffer.Offset;
|
||||
}
|
||||
|
||||
public async UniTask OutputAsync(IBufferWriter<byte> writer, object options = null)
|
||||
{
|
||||
var (Owner, Count) = await outq.ReadAsync().ConfigureAwait(false);
|
||||
WriteOut(writer, Owner, Count);
|
||||
}
|
||||
|
||||
private static void WriteOut(IBufferWriter<byte> writer, BufferOwner Owner, int Count)
|
||||
{
|
||||
var target = writer.GetSpan(Count);
|
||||
Owner.Memory.Span.Slice(0, Count).CopyTo(target);
|
||||
writer.Advance(Count);
|
||||
Owner.Dispose();
|
||||
}
|
||||
|
||||
protected internal override BufferOwner CreateBuffer(int needSize)
|
||||
{
|
||||
return MemoryPool<byte>.Shared.Rent(needSize);
|
||||
}
|
||||
|
||||
internal class OutputQ : QueuePipe<(BufferOwner Owner, int Count)>,
|
||||
IKcpCallback
|
||||
{
|
||||
public void Output(BufferOwner buffer, int avalidLength)
|
||||
{
|
||||
Write((buffer, avalidLength));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c30d30fa46372948b60bd56eec47fe6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,50 +0,0 @@
|
||||
using System.Buffers;
|
||||
|
||||
namespace System.Net.Sockets.Kcp
|
||||
{
|
||||
public abstract class KcpOutputWriter : IKcpOutputWriter
|
||||
{
|
||||
public int UnflushedBytes { get; set; }
|
||||
public IMemoryOwner<byte> MemoryOwner { get; set; }
|
||||
public void Flush()
|
||||
{
|
||||
Output(MemoryOwner, UnflushedBytes);
|
||||
MemoryOwner = null;
|
||||
UnflushedBytes = 0;
|
||||
}
|
||||
|
||||
public void Advance(int count)
|
||||
{
|
||||
UnflushedBytes += count;
|
||||
}
|
||||
|
||||
public Memory<byte> GetMemory(int sizeHint = 0)
|
||||
{
|
||||
if (MemoryOwner == null)
|
||||
{
|
||||
MemoryOwner = MemoryPool<byte>.Shared.Rent(2048);
|
||||
}
|
||||
return MemoryOwner.Memory.Slice(UnflushedBytes);
|
||||
}
|
||||
|
||||
public Span<byte> GetSpan(int sizeHint = 0)
|
||||
{
|
||||
if (MemoryOwner == null)
|
||||
{
|
||||
MemoryOwner = MemoryPool<byte>.Shared.Rent(2048);
|
||||
}
|
||||
return MemoryOwner.Memory.Span.Slice(UnflushedBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Socket发送是要pin byte[],为了不阻塞KcpFlush,动态缓存是必须的。
|
||||
/// </summary>
|
||||
/// <param name="buffer"></param>
|
||||
/// <param name="avalidLength"></param>
|
||||
public abstract void Output(IMemoryOwner<byte> buffer, int avalidLength);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user