mirror of
https://github.com/Facepunch/Facepunch.Steamworks.git
synced 2025-05-12 14:49:48 +03:00
Compare commits
1195 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
aa87fe557f | ||
|
0595c9c796 | ||
|
b4d3a65f86 | ||
|
a0aac6a82a | ||
|
6d1b9b9602 | ||
|
e4455258ac | ||
|
5783d89634 | ||
|
3b58a3dc92 | ||
|
de10d5ced4 | ||
|
520ac1ca51 | ||
|
ee6572a380 | ||
|
963729bf64 | ||
|
eec3c05ecd | ||
|
62a1ae78e5 | ||
|
7f747b0468 | ||
|
a80e8590d5 | ||
|
09db39d9e3 | ||
|
6dd32eb5c4 | ||
|
d18086a1b8 | ||
|
93223cb30a | ||
|
6deb4b64d2 | ||
|
f8960c8971 | ||
|
4463739be5 | ||
|
5475972ae7 | ||
|
a3419df3b9 | ||
|
c18a018c3f | ||
|
e21c42e8a2 | ||
|
8a5f229a2f | ||
|
10f3323318 | ||
|
4e7e0ef8c4 | ||
|
9160882a9b | ||
|
4b12fa14dc | ||
|
e81d1ac682 | ||
|
814488652b | ||
|
aab6d0d081 | ||
|
0fda7e39fe | ||
|
04b921b33d | ||
|
5cb1496e80 | ||
|
2675b3201b | ||
|
df99a3e1ac | ||
|
a16c92d9c6 | ||
|
9ff422533f | ||
|
5d944374b2 | ||
|
36e3f3a58f | ||
|
86aa1439aa | ||
|
6a204680da | ||
|
ed1c690d7b | ||
|
30ff3a3d85 | ||
|
0455e7fc72 | ||
|
045a3963b0 | ||
|
45df99416e | ||
|
cf9744913c | ||
|
214096e376 | ||
|
f3ee5bec4e | ||
|
2088f14c05 | ||
|
26eb429654 | ||
|
70b2a301ca | ||
|
2f8c19a1d1 | ||
|
59db8fac8a | ||
|
12663f0d81 | ||
|
c106d01fcb | ||
|
132b1a579b | ||
|
141dbfdaa1 | ||
|
f005600957 | ||
|
480137a490 | ||
|
3b0fa8106c | ||
|
38c2ffd796 | ||
|
30f35c3aae | ||
|
1c98852d7c | ||
|
40bcf2e95a | ||
|
bfa94d89fa | ||
|
821975435c | ||
|
959249d04a | ||
|
454c686368 | ||
|
b47e1e6f55 | ||
|
fa34bc76f9 | ||
|
ca77bd07bc | ||
|
997baf0a07 | ||
|
b5dc75d062 | ||
|
a51ccbb69d | ||
|
1c21400d3e | ||
|
21fb722e3f | ||
|
e96d97c5b5 | ||
|
dd613232d3 | ||
|
42c7755a58 | ||
|
1a1d023356 | ||
|
3eb302ac54 | ||
|
9dd286eed4 | ||
|
ba0f4d3e10 | ||
|
8efc0414c4 | ||
|
2be5012647 | ||
|
b01e98e60c | ||
|
285e88b332 | ||
|
3eacc55b1e | ||
|
1bae585602 | ||
|
da34905e07 | ||
|
57d0e40ebb | ||
|
f18fcb6aa8 | ||
|
d5b49fdeab | ||
|
1fe8f51915 | ||
|
55514d42ac | ||
|
d2fbf89f99 | ||
|
cca1b0305e | ||
|
f567313ea0 | ||
|
c7ec49abe0 | ||
|
5c11508f41 | ||
|
28effd140b | ||
|
616571a3a9 | ||
|
27a0048c0e | ||
|
47b9aca324 | ||
|
e6df29654f | ||
|
fa57c676e2 | ||
|
8057413ea3 | ||
|
4a06c64ded | ||
|
c5c31280c1 | ||
|
8f579f6e55 | ||
|
bc6600736c | ||
|
81c5ca7761 | ||
|
5be8940c83 | ||
|
f2ac10deb3 | ||
|
088ba90f65 | ||
|
31ffaa3e6e | ||
|
110c0f2bad | ||
|
5c30b6039a | ||
|
68977092f3 | ||
|
aa6a780185 | ||
|
a10a5b40cd | ||
|
ea3743bd73 | ||
|
8be43b4dde | ||
|
b4de0927f3 | ||
|
9fecd91bed | ||
|
ae70292e7b | ||
|
ad1cfca69f | ||
|
cb792b0f04 | ||
|
b71c83ad13 | ||
|
cf3e252d2e | ||
|
8d25edf498 | ||
|
fd6f7c8586 | ||
|
bd6693146c | ||
|
fdbb97748b | ||
|
d8b6cf7c83 | ||
|
6291c8f117 | ||
|
73b5c9ceb6 | ||
|
699b7c0850 | ||
|
e4a35ff64d | ||
|
a627bf76c8 | ||
|
7609e61a14 | ||
|
5645a91e7f | ||
|
74207eeaf3 | ||
|
44af74e892 | ||
|
d373077c9a | ||
|
f739f9b588 | ||
|
0d9db585f5 | ||
|
11bc35f254 | ||
|
0eb3672674 | ||
|
f887d8a9ba | ||
|
c4ffb5eac7 | ||
|
f84872b38c | ||
|
4a2eb22ec7 | ||
|
ea1408392b | ||
|
5fd6de76d7 | ||
|
91d03c957f | ||
|
6d0cfa1ec8 | ||
|
88c742d415 | ||
|
68a1886283 | ||
|
ce3c395b49 | ||
|
24431ca9db | ||
|
a8794e6321 | ||
|
49f25b3936 | ||
|
6e67204ddc | ||
|
401f53b30d | ||
|
943c4f9a30 | ||
|
498c1b9a32 | ||
|
5fdffff5c4 | ||
|
384cbf6b4c | ||
|
c7ac4997ed | ||
|
950b256c27 | ||
|
75dc868064 | ||
|
c0c32e500a | ||
|
ec3012484a | ||
|
8a1722053e | ||
|
6e2ab8b735 | ||
|
198b5555a2 | ||
|
30d52cd541 | ||
|
de69dd228f | ||
|
b0a64798cf | ||
|
af36007f5d | ||
|
ed45805029 | ||
|
53fc721ea9 | ||
|
d4356b75dd | ||
|
5c95620ee6 | ||
|
a3bd199b11 | ||
|
7e4f1400c3 | ||
|
f568958a39 | ||
|
b8df8aff4a | ||
|
d080548c20 | ||
|
c25bc70d53 | ||
|
a9391b72d5 | ||
|
b522f5affa | ||
|
9101b82450 | ||
|
8ea013d69e | ||
|
025cc9b3f0 | ||
|
d58d95fe38 | ||
|
9d8a9a1e9a | ||
|
392b57e18d | ||
|
9b487aae0e | ||
|
b813ee7a17 | ||
|
04d1c86954 | ||
|
c10167bb91 | ||
|
1f5b5bea5f | ||
|
aa1751071d | ||
|
0beaeb2e9d | ||
|
abb4b7f6b6 | ||
|
a0974e9ba3 | ||
|
ecdf217d08 | ||
|
4c353264cb | ||
|
6d4639376d | ||
|
2f8acff629 | ||
|
cf1260983c | ||
|
ead77b6567 | ||
|
f9b6448469 | ||
|
36e5e50d85 | ||
|
1797505960 | ||
|
2287e5527b | ||
|
e48a0db798 | ||
|
d06054875a | ||
|
23129f3a83 | ||
|
3a11b6f8b3 | ||
|
d9bf9abeac | ||
|
1a1809ba40 | ||
|
08a4136a3e | ||
|
53d86e7e3f | ||
|
e9978ec55b | ||
|
773ea24aa4 | ||
|
b265084d18 | ||
|
c24b247094 | ||
|
e6c0167c48 | ||
|
5aeeaa0cd7 | ||
|
e5b467ae35 | ||
|
08d36b7ea1 | ||
|
ebf77a8fde | ||
|
66b221984f | ||
|
09256aa4a3 | ||
|
2acbf964de | ||
|
631969360c | ||
|
9db103cb2f | ||
|
8db2b46729 | ||
|
93e21a5f79 | ||
|
600c7dbcc4 | ||
|
f7d9acd05a | ||
|
61b09add87 | ||
|
57775e5d10 | ||
|
d900b6e217 | ||
|
13feee328d | ||
|
49b55c74b8 | ||
|
8b2a888feb | ||
|
b0d23eff22 | ||
|
bf60680d87 | ||
|
a8f1ac3799 | ||
|
122c2b0a57 | ||
|
a60281dc41 | ||
|
5d9e4b5c0b | ||
|
4d98ea3d51 | ||
|
263fb219a8 | ||
|
998c18764a | ||
|
59eabc1302 | ||
|
b45ac59a21 | ||
|
f191ee5e42 | ||
|
895e11e801 | ||
|
61a103919b | ||
|
a043019f0a | ||
|
546066d4cc | ||
|
d526fa5e9f | ||
|
bffa403e39 | ||
|
a075810468 | ||
|
f1e8664d28 | ||
|
c9053b0a91 | ||
|
403488dfcb | ||
|
d990b537a3 | ||
|
b52a63bc8b | ||
|
23b3304332 | ||
|
52ecc0b594 | ||
|
2843749918 | ||
|
faee6f6cf2 | ||
|
29f426baf0 | ||
|
ae900f84bc | ||
|
2928939c9f | ||
|
7c20b57957 | ||
|
18fbabaf2c | ||
|
86a8f80584 | ||
|
44196682c8 | ||
|
41c1d0da08 | ||
|
3c8a2f6cd1 | ||
|
afd314627d | ||
|
e7a6a00675 | ||
|
4871c634fb | ||
|
fc74049123 | ||
|
f495d18ece | ||
|
8b2599be98 | ||
|
c80421e9a9 | ||
|
428c2425a0 | ||
|
aab047717b | ||
|
bc9801c36a | ||
|
f517587edc | ||
|
49252f49f5 | ||
|
23a5964171 | ||
|
dfa98564f7 | ||
|
4d2d15f3af | ||
|
16d4b4f6f8 | ||
|
8f36f0c939 | ||
|
ffa48fb03c | ||
|
011c596cb1 | ||
|
4108895749 | ||
|
e3ac585144 | ||
|
c2a980227d | ||
|
4b10d72d12 | ||
|
abb749078b | ||
|
c8cb180b78 | ||
|
d58dfdf4d2 | ||
|
a934498263 | ||
|
1d3585fa6a | ||
|
b6c24ce04c | ||
|
ceb66b731e | ||
|
8ecd08fa50 | ||
|
3a0e68c6e1 | ||
|
a7954f9e21 | ||
|
d8e5a48f65 | ||
|
92b45c7596 | ||
|
ed96cafbe4 | ||
|
85339a079a | ||
|
6c84df0ef8 | ||
|
2872bb92f7 | ||
|
841d665046 | ||
|
f60b54df33 | ||
|
cfa77bc9e2 | ||
|
2db3bb9bb3 | ||
|
427524abc9 | ||
|
06d0059d87 | ||
|
f3443935b2 | ||
|
e4e3b0dbce | ||
|
1a263c09cf | ||
|
6fbc1e80f3 | ||
|
7c82a9fc60 | ||
|
8dc011964f | ||
|
6e896c2085 | ||
|
1fd8ea89a9 | ||
|
773605c841 | ||
|
d42996142f | ||
|
22e963250e | ||
|
d919a1e635 | ||
|
4e98ae5027 | ||
|
19e64429c4 | ||
|
710c6a0ce7 | ||
|
2e6db5fe37 | ||
|
127de84c8c | ||
|
e9d130572a | ||
|
2fc5206b38 | ||
|
04ad04f95d | ||
|
32fbf63644 | ||
|
61f3809b4e | ||
|
c5f1033aeb | ||
|
6587db5a9d | ||
|
f1fdf29124 | ||
|
8ceecd7350 | ||
|
5832c3ea82 | ||
|
84063b674c | ||
|
3e95d41692 | ||
|
2f63117c32 | ||
|
8b231bf4d6 | ||
|
f549a69bc0 | ||
|
4997a74d15 | ||
|
e3ce99bc12 | ||
|
455a9f8956 | ||
|
83aa37ce4f | ||
|
06169693d0 | ||
|
796976cd47 | ||
|
39952fe50e | ||
|
9ad3a57ad9 | ||
|
5666bb432e | ||
|
3c2eeb7f2f | ||
|
a7666d7d51 | ||
|
71b977ef7e | ||
|
a02d1e87a7 | ||
|
ac8983ee94 | ||
|
5c36a5c338 | ||
|
58eae03ae4 | ||
|
4f6e8bf8d1 | ||
|
1a02a9c363 | ||
|
1e5dc7b2ea | ||
|
4fafe33a93 | ||
|
717ec3942f | ||
|
c6c73a36e9 | ||
|
38b1ed5f88 | ||
|
2fb1426479 | ||
|
7a4f0c029a | ||
|
968e658913 | ||
|
1273b5985f | ||
|
d2e4417ef2 | ||
|
fc42dca5bf | ||
|
17434b2910 | ||
|
7c1a218553 | ||
|
6f5bde4f79 | ||
|
3b4d4bf3d8 | ||
|
689ada6eca | ||
|
b60fa061ed | ||
|
e7deae2ae3 | ||
|
caea5ccb9b | ||
|
39bc7b5c1b | ||
|
11cc473a6e | ||
|
7f4e0567a6 | ||
|
7fbc333547 | ||
|
a24ae4bac5 | ||
|
a53a0f537c | ||
|
71af8c0e9b | ||
|
74ec75b708 | ||
|
617275db3f | ||
|
69e2e9bd39 | ||
|
016b86ce8e | ||
|
4cef345d95 | ||
|
f53e1aaba0 | ||
|
d5abb32aeb | ||
|
810cb3623f | ||
|
1df586305d | ||
|
690db722eb | ||
|
6dbed6a91d | ||
|
f42fa5942f | ||
|
12c26384e7 | ||
|
02e9063db8 | ||
|
9442689b02 | ||
|
040291ed22 | ||
|
db41c0f407 | ||
|
4b8e1e33af | ||
|
0300b46ed3 | ||
|
57f3b334b5 | ||
|
efd2fa2291 | ||
|
fdc5b49587 | ||
|
645e7bd91e | ||
|
6a0a46f495 | ||
|
caf52e4c4b | ||
|
78761d9fd7 | ||
|
56efc9f48b | ||
|
08405459bd | ||
|
97b85172e2 | ||
|
c4eff7f61a | ||
|
fd50e3ba71 | ||
|
15dc2782cc | ||
|
1d242fbc98 | ||
|
a0478a6040 | ||
|
615645a30e | ||
|
552d5251f8 | ||
|
bddac0ccc9 | ||
|
fa48a1ce33 | ||
|
bce40a3c3a | ||
|
ade772d195 | ||
|
cb06574820 | ||
|
1c5cdd2d39 | ||
|
ae1f648fa6 | ||
|
1ac22e1407 | ||
|
77f3e09e98 | ||
|
985aefc2de | ||
|
41a0b31644 | ||
|
ef071d3d71 | ||
|
7c50db6997 | ||
|
5b32943aa8 | ||
|
d64ef909c6 | ||
|
52381d4af8 | ||
|
33703be387 | ||
|
adf39138a4 | ||
|
253c206f71 | ||
|
33830e274e | ||
|
c93fe0ca11 | ||
|
c69b817d62 | ||
|
2ad31e1375 | ||
|
c60612b8b0 | ||
|
e4c9e9d034 | ||
|
cad7edcec0 | ||
|
5c973b0092 | ||
|
ffb0c7a830 | ||
|
91e9e162f3 | ||
|
711bc7cb3d | ||
|
761ff33663 | ||
|
2c4fc82ae2 | ||
|
6b9b7da34b | ||
|
7c53fc580d | ||
|
5f7bd08320 | ||
|
f06b4b431b | ||
|
a5bd78a597 | ||
|
778b1081cb | ||
|
a1599e3226 | ||
|
cf2bc51c54 | ||
|
208af219d2 | ||
|
17d7263973 | ||
|
fed6ccdefa | ||
|
98915f0950 | ||
|
a2942bd098 | ||
|
d671c1ddc8 | ||
|
fff2fc6098 | ||
|
f629b1c663 | ||
|
7a30b76a26 | ||
|
69ec868227 | ||
|
6981eb4a73 | ||
|
fdee0bfc1e | ||
|
b6cecf0082 | ||
|
6a2db11c5d | ||
|
326d27e98e | ||
|
44dfa45337 | ||
|
99dcc83ab0 | ||
|
f014681cc4 | ||
|
69773bb033 | ||
|
8a6bbb9a91 | ||
|
d290c26db1 | ||
|
43f09dc2ed | ||
|
586f4ee6f2 | ||
|
1980a2106a | ||
|
d0b4ce0451 | ||
|
075e5460a4 | ||
|
eae18553da | ||
|
10c099d910 | ||
|
b85fe5ffd8 | ||
|
000358aae8 | ||
|
8c986113de | ||
|
360645962f | ||
|
f65cfecc64 | ||
|
85c55a5bb1 | ||
|
9339477c89 | ||
|
8ea4231778 | ||
|
39c1e8da1e | ||
|
60377c9c5b | ||
|
0342f8a712 | ||
|
3212f39be5 | ||
|
05e12c32e1 | ||
|
49bb3644bd | ||
|
f8798f2f4e | ||
|
cf458a515a | ||
|
6c0e3df84c | ||
|
c6ac47c0c3 | ||
|
1dd679c391 | ||
|
ad21e90e90 | ||
|
c625bbaef9 | ||
|
966ad90630 | ||
|
eceeb2cb8f | ||
|
18f81573f5 | ||
|
d40efa8612 | ||
|
b6fa05afa2 | ||
|
060af634d7 | ||
|
a020474856 | ||
|
503d8964ea | ||
|
d811afc741 | ||
|
45471330d4 | ||
|
82fe950bbf | ||
|
89e93d6c2a | ||
|
6ecc68e5d7 | ||
|
1dc804c7ac | ||
|
8560d94a18 | ||
|
43c3aa35f5 | ||
|
a82a56bd4c | ||
|
3516422c3f | ||
|
fd320e2848 | ||
|
f42fdfd09a | ||
|
a4a1b32bc7 | ||
|
2a74b309dd | ||
|
78c69b15a8 | ||
|
0ae14db7f8 | ||
|
63b3cae096 | ||
|
ea97de9c02 | ||
|
dda27d2c61 | ||
|
2a55d7a8e8 | ||
|
a0d9fdeab1 | ||
|
d1cc0da526 | ||
|
533b6ad28d | ||
|
9bb5b5178e | ||
|
b171e22861 | ||
|
16851f1228 | ||
|
cdeccc5afe | ||
|
f77332a41f | ||
|
14d947c7ba | ||
|
12ab3f1248 | ||
|
71d8226e28 | ||
|
ebfecfe25c | ||
|
3b2c7a5a16 | ||
|
91083d5d16 | ||
|
9d363de6b8 | ||
|
91f8f3ed29 | ||
|
ab23781a5d | ||
|
00bdc717c6 | ||
|
14c5bace46 | ||
|
0265eda9f0 | ||
|
5fdbf02b29 | ||
|
4ed8a4250b | ||
|
ea0f19ff8e | ||
|
6be5826f31 | ||
|
ce3525bf1d | ||
|
270b3f0300 | ||
|
6c41ef2e51 | ||
|
1c5eeedf40 | ||
|
9b2ad8e49a | ||
|
3eae3314b6 | ||
|
16ce5f4d63 | ||
|
1c1925bae9 | ||
|
87ff387ca6 | ||
|
239273a715 | ||
|
068beddc04 | ||
|
93c4de7eda | ||
|
c5ec70447b | ||
|
5f9ad75741 | ||
|
362ba26729 | ||
|
fbad8b8d6e | ||
|
e3840a9a3a | ||
|
5a68e15676 | ||
|
994cdee49e | ||
|
157d0d676e | ||
|
96eeea1662 | ||
|
cf0e3417de | ||
|
8d5f140e09 | ||
|
fb97dbee2e | ||
|
ab535d367d | ||
|
38a29c6059 | ||
|
51ab76893a | ||
|
5938bf59d4 | ||
|
6eae474e6e | ||
|
b2cfbe23c5 | ||
|
a80ee82e53 | ||
|
26b79db7e4 | ||
|
850c37e77d | ||
|
32850da719 | ||
|
8916161464 | ||
|
4160e72141 | ||
|
d16db7c13c | ||
|
868c5672b9 | ||
|
0042a63db1 | ||
|
1f7e78be09 | ||
|
93d20de83b | ||
|
4237204f45 | ||
|
86e4576baf | ||
|
ff48493ceb | ||
|
84627fe69f | ||
|
eb51e359d4 | ||
|
87cd93bfde | ||
|
10a82adca9 | ||
|
cbc154da66 | ||
|
8b78f8a1a7 | ||
|
8da5ab2cd0 | ||
|
a32ab732d1 | ||
|
3bf1950068 | ||
|
c609d7bb87 | ||
|
d67bd7d8ef | ||
|
f129ff7cac | ||
|
b39ee80ecd | ||
|
74ef28b9fc | ||
|
e68dc15454 | ||
|
10e228f765 | ||
|
bb2ede3870 | ||
|
0c19a87813 | ||
|
2260b222f5 | ||
|
f91b01d195 | ||
|
683925430d | ||
|
b74d45814a | ||
|
1625268f5d | ||
|
0d509bf126 | ||
|
67de9c8e96 | ||
|
d2ce2fe13b | ||
|
37f6192213 | ||
|
aa666a3149 | ||
|
5a25d750f2 | ||
|
194ca8d8b3 | ||
|
11b7fde17d | ||
|
396be12edd | ||
|
67170a2da4 | ||
|
a59e8f9134 | ||
|
764b6246e8 | ||
|
da64466b72 | ||
|
053f04bc2f | ||
|
1137076fa7 | ||
|
dd06f22cee | ||
|
3b89a53da3 | ||
|
4625e22a55 | ||
|
39705d5a2a | ||
|
e275b209b3 | ||
|
f2ae791e15 | ||
|
e4663ecc68 | ||
|
bab5664568 | ||
|
30a96ccae7 | ||
|
e2e2554e88 | ||
|
0e4946e550 | ||
|
e9f5898b6c | ||
|
6dd5164f34 | ||
|
9af8935f47 | ||
|
6c1dd241ba | ||
|
eb16bebae9 | ||
|
99e85e9a98 | ||
|
934bd2154a | ||
|
ddd5cc03f3 | ||
|
ebcd96326a | ||
|
e5a89b0550 | ||
|
d2a3e0b1da | ||
|
5a780c4bc0 | ||
|
573bf39789 | ||
|
bc658d0a31 | ||
|
d4843adcab | ||
|
f18de016b1 | ||
|
650fb08522 | ||
|
79ed6a299a | ||
|
ebc1336da3 | ||
|
7e02ad736d | ||
|
f4e2efaca1 | ||
|
b6f651b45c | ||
|
5782160623 | ||
|
6c5c94e834 | ||
|
ea85ddbb6f | ||
|
1abc9bf973 | ||
|
a1c64cfeda | ||
|
da17648ade | ||
|
6e350f4d08 | ||
|
28e8f261e2 | ||
|
a4f446d009 | ||
|
59c0550cfc | ||
|
603bd95c38 | ||
|
8e97489def | ||
|
51b2b7dee2 | ||
|
50ddedfd6e | ||
|
353ddc5a8d | ||
|
ede5320069 | ||
|
8ceecaf1b0 | ||
|
bf6883deb9 | ||
|
a634f80790 | ||
|
c19982f3b1 | ||
|
8107297262 | ||
|
c1d611dae7 | ||
|
3255135df1 | ||
|
90d9ae8c4c | ||
|
b134c8708f | ||
|
e4ddd1fe6c | ||
|
ca20e5a75a | ||
|
088e9918e0 | ||
|
6fa147141a | ||
|
ee7e4e076a | ||
|
c5e507fb15 | ||
|
920ea6ce6b | ||
|
f7e09ec7bf | ||
|
41dfaeb2f7 | ||
|
1f0e34cf40 | ||
|
e096ba5c6c | ||
|
2ea8585c48 | ||
|
d211dd40e1 | ||
|
dcd1ea8503 | ||
|
e7aa122c1f | ||
|
ca96362a5f | ||
|
9cf553a786 | ||
|
db1cfde383 | ||
|
2d2be118d3 | ||
|
a2cd4b099c | ||
|
c2a9c7b226 | ||
|
3b9f6592ef | ||
|
7a2fc78105 | ||
|
8935311b03 | ||
|
cd30b85444 | ||
|
027a110c61 | ||
|
6b26323bf8 | ||
|
173a132d6e | ||
|
76c82bff25 | ||
|
fe0d934bfc | ||
|
d9da40c0e8 | ||
|
cce25e6f77 | ||
|
d6eb2c8041 | ||
|
429d1937f9 | ||
|
fac123324d | ||
|
39a63f6906 | ||
|
db7c8d66a4 | ||
|
cf8aa9501c | ||
|
ede67d51cd | ||
|
06446a8bc0 | ||
|
afb2e286f4 | ||
|
34d6b15fb8 | ||
|
199ad77406 | ||
|
ebea536334 | ||
|
f69710cc15 | ||
|
4296e4e748 | ||
|
96df72c291 | ||
|
d7a546d913 | ||
|
6719c6d0a4 | ||
|
7e09c9d56f | ||
|
b6266a7386 | ||
|
d91ba6d84a | ||
|
feec8f6842 | ||
|
2b43b9b992 | ||
|
11ad696f7c | ||
|
1eb16f34b8 | ||
|
63aff6582f | ||
|
d5f762fa32 | ||
|
177ca2b9e7 | ||
|
00bd53f0ec | ||
|
9d086dbcf6 | ||
|
21ff07288d | ||
|
51d0d21674 | ||
|
18262fd4f2 | ||
|
1e1eb00e04 | ||
|
0bf379a41b | ||
|
15b04eec2a | ||
|
4b9eba285a | ||
|
26a64f64e7 | ||
|
879a284de3 | ||
|
0b55f13306 | ||
|
07f9f00cb4 | ||
|
12e26e3f5d | ||
|
6c4a83800a | ||
|
fba1986812 | ||
|
c0a6a80089 | ||
|
80a383730b | ||
|
971751f89d | ||
|
96511dcc64 | ||
|
e69e25a1f1 | ||
|
6c6c8dc696 | ||
|
7d66fc9744 | ||
|
13280cd57c | ||
|
834bb451a7 | ||
|
5f3ed7467a | ||
|
438127288a | ||
|
8ebaa933e4 | ||
|
24df7fb6ad | ||
|
812a435031 | ||
|
b86d7ff019 | ||
|
6286e43066 | ||
|
e792d3b3b5 | ||
|
a2cbe8dd22 | ||
|
a1ca267d93 | ||
|
2d1e529abf | ||
|
22dda179a3 | ||
|
dc6b9fa5f7 | ||
|
55d3fd6b75 | ||
|
617183184d | ||
|
2e8fe41040 | ||
|
83d71d78a4 | ||
|
1e484a07ed | ||
|
616fcc400d | ||
|
072ef291a0 | ||
|
e8741adea5 | ||
|
46f56c24f3 | ||
|
ff1d866374 | ||
|
227aeee904 | ||
|
9270eaef07 | ||
|
476321c026 | ||
|
80bf89c9e6 | ||
|
835770772f | ||
|
e94866828a | ||
|
e8a59e3a10 | ||
|
372052a7fb | ||
|
41ee808639 | ||
|
0a115edae9 | ||
|
7b7cfa29c4 | ||
|
144f401d2c | ||
|
a40334551b | ||
|
99c77f1997 | ||
|
ebef55c428 | ||
|
2fb0df5ae3 | ||
|
aa3a6d4d24 | ||
|
2474c3de99 | ||
|
c58fc3f217 | ||
|
aec8f756e8 | ||
|
6b5f8f7481 | ||
|
72ef9015b3 | ||
|
63b31976c0 | ||
|
bf2a074547 | ||
|
6982d05042 | ||
|
24c0edcbcb | ||
|
c4617c5884 | ||
|
2ee5fa4a5d | ||
|
71048f1041 | ||
|
42d47a14c7 | ||
|
3895fd33aa | ||
|
727741b81a | ||
|
e71cce0817 | ||
|
7abd06a806 | ||
|
28df21a19b | ||
|
c4343ee318 | ||
|
1f121f508a | ||
|
dd31847990 | ||
|
2587643b25 | ||
|
70c1513c19 | ||
|
8d410969c3 | ||
|
ef8234b958 | ||
|
68b409d163 | ||
|
04c7eb59dc | ||
|
a82f6fc8ed | ||
|
c4f33a1d3d | ||
|
e88535ac57 | ||
|
9a9a310b5f | ||
|
d015d00974 | ||
|
09c4a4f63e | ||
|
9e8bf53f42 | ||
|
0beef36548 | ||
|
3a4bb29f7e | ||
|
59d21a7efb | ||
|
d134c5e6ff | ||
|
f0e4c63267 | ||
|
a2807dbbcf | ||
|
44a6f42f8e | ||
|
bda8b5b956 | ||
|
627fa4c825 | ||
|
2ecf323ae0 | ||
|
796fd29e32 | ||
|
2da780df7c | ||
|
6c434df638 | ||
|
6d78155ec6 | ||
|
958d4675af | ||
|
916d9afdc9 | ||
|
c8e5c0ca5a | ||
|
ba6132715c | ||
|
650d221baf | ||
|
e66a00d212 | ||
|
b7195adc89 | ||
|
5991839c27 | ||
|
8d202b4645 | ||
|
59f7e0ca0a | ||
|
01e7d1d378 | ||
|
8585dca101 | ||
|
4a663f8c9f | ||
|
0633bae582 | ||
|
d2331e68e2 | ||
|
3085ec266c | ||
|
1ccea72a13 | ||
|
d60ebf5fdd | ||
|
6ce4e637d9 | ||
|
d6b3966c9d | ||
|
63a12ff7c6 | ||
|
d98f7fd1fe | ||
|
6e807c8e4d | ||
|
6dc680cbab | ||
|
54dab0c2a4 | ||
|
d959dafae0 | ||
|
75530c6bef | ||
|
33393e8725 | ||
|
3001f2a5c4 | ||
|
7913ccd171 | ||
|
e2ef2b0bf7 | ||
|
47f153ffa6 | ||
|
1d0fe2b814 | ||
|
7d30ffc734 | ||
|
60933de240 | ||
|
a3a4c87ede | ||
|
616040da42 | ||
|
2e65cfe9bb | ||
|
d7fd203c02 | ||
|
e8b6f31bb2 | ||
|
0366c39690 | ||
|
b6c7916684 | ||
|
72bae11073 | ||
|
1cf2130703 | ||
|
13c8b543cc | ||
|
2b4c62bd28 | ||
|
cc4bdcea8d | ||
|
c6bd69092a | ||
|
4ba430601a | ||
|
79f398da04 | ||
|
a6b440324b | ||
|
d614b1544b | ||
|
fd14512e28 | ||
|
c5af1f91cf | ||
|
5dcfda6c15 | ||
|
9516d1ed7a | ||
|
5067c32eed | ||
|
ba32817183 | ||
|
bef249000a | ||
|
cc4fdd5324 | ||
|
abea08d046 | ||
|
6aa5bcf1ac | ||
|
a1f24c5f24 | ||
|
bcd8495d6e | ||
|
75484c1e00 | ||
|
beccb5e5e9 | ||
|
c40037784e | ||
|
72c5427be6 | ||
|
b62f7f6b87 | ||
|
7bd8aaa793 | ||
|
84954436f7 | ||
|
61268b973e | ||
|
c6cb8a2f81 | ||
|
a26ae696c2 | ||
|
1c04459cdb | ||
|
e1c738fc8b | ||
|
7eb4a88cee | ||
|
6c4296a0fc | ||
|
7e38750f2e | ||
|
e3f84eac32 | ||
|
e6c395b2f6 | ||
|
bf7ab5598b | ||
|
c9d36eb4ac | ||
|
a2972098d9 | ||
|
d53c59f09b | ||
|
ed632baf38 | ||
|
3ecd7e4e4e | ||
|
27f640fd5a | ||
|
2108dc3b76 | ||
|
bf21cb9df3 | ||
|
499b0d64c5 | ||
|
598f44e9f8 | ||
|
d129f3757a | ||
|
ea4c6d72b5 | ||
|
b327ab70f1 | ||
|
28766081b5 | ||
|
67fb987288 | ||
|
5890fea9e6 | ||
|
892edf371e | ||
|
d944c6c7ae | ||
|
e5b6d99bef | ||
|
111495100f | ||
|
1a47b32458 | ||
|
3002419af0 | ||
|
0a115f8ea4 | ||
|
0a9f3f2281 | ||
|
e3312d3387 | ||
|
4390724cbe | ||
|
3752e75316 | ||
|
b92fba15ec | ||
|
38f3f6d9ea | ||
|
303da3753d | ||
|
67fd7fe00a | ||
|
d417f22336 | ||
|
53709bf5d0 | ||
|
3ffe684726 | ||
|
7e3527799a | ||
|
836f6e285c | ||
|
788145c265 | ||
|
6ea0e366f5 | ||
|
549ceb0562 | ||
|
906cff4416 | ||
|
d3ebe4e2f2 | ||
|
8fa8da4939 | ||
|
27c2b83bea | ||
|
9657f3b32e | ||
|
2cff8ccea1 | ||
|
d1ada9464d | ||
|
16d3b048af | ||
|
2ebecd1548 | ||
|
01cf0f4cec | ||
|
3a8ed89583 | ||
|
277ae79950 | ||
|
bb846c28aa | ||
|
f693bff938 | ||
|
fab24796ab | ||
|
a956a1005c | ||
|
fd82d26367 | ||
|
412d13cbbc | ||
|
1e0f7a835c | ||
|
c43b4767dc | ||
|
2fbbd66c45 | ||
|
66f771fee2 | ||
|
04d2a2aa5d | ||
|
5c320bab12 | ||
|
ca7107c8d3 | ||
|
f9f18eec74 | ||
|
58b4b73800 | ||
|
8d2ccf0538 | ||
|
2c343d27b1 | ||
|
1369dc2a3f | ||
|
e9c913beea | ||
|
f10dd56ddd | ||
|
c38f45e630 | ||
|
df9b0d3114 | ||
|
45024c57f3 | ||
|
5426339bd0 | ||
|
b5767fd1b6 | ||
|
287744fd83 | ||
|
b06411c42c | ||
|
b7727a10e1 | ||
|
d7808bf424 | ||
|
b7564630cd | ||
|
6e7afc1ac9 | ||
|
62efd08e7a | ||
|
5fdcf82eac | ||
|
967f9307d3 | ||
|
8256cca36c | ||
|
f95c320469 | ||
|
d06f662e6c | ||
|
24affc78d8 | ||
|
c297033ef7 | ||
|
f64d0d15af | ||
|
255e80b58d | ||
|
5ac65c9fb9 | ||
|
15bfd887bd | ||
|
9f3ecfd66e | ||
|
74ef4d49ad | ||
|
5cef85adb4 | ||
|
a1d458de00 | ||
|
88e2568e9f | ||
|
0f26139d38 | ||
|
f011ff8d8b | ||
|
ef2fb26911 | ||
|
9fe91b48b6 | ||
|
54fe75b2bc | ||
|
270595a540 | ||
|
657c04b399 | ||
|
01dbec678c | ||
|
aeec6f59ef | ||
|
6a5603a121 | ||
|
b8e6614f67 | ||
|
0e63be99c0 | ||
|
5c62314f96 | ||
|
dec523602d | ||
|
158a102060 | ||
|
8aed047784 | ||
|
941ab6e797 | ||
|
53c47d5a12 | ||
|
9da329bb7d | ||
|
600c4c53c0 | ||
|
d56e380c72 | ||
|
b2be137107 | ||
|
4e4fdd63ee | ||
|
eabf5b84e2 | ||
|
41400f56e6 | ||
|
019d46580e | ||
|
d8a25afb46 | ||
|
3490d05b40 | ||
|
9d8141475f | ||
|
755b238e1d | ||
|
26c1a0af85 | ||
|
a53340ddea | ||
|
aa28a78d8c | ||
|
f838cf6b98 | ||
|
8bf391a300 | ||
|
84e38601d6 | ||
|
2fef034547 | ||
|
c27df08194 | ||
|
11733c48e7 | ||
|
44dcf4d150 | ||
|
480daeb673 | ||
|
947fc190d2 | ||
|
65dec9d809 | ||
|
d5eca996cd | ||
|
0b11025afe | ||
|
1efdd690c2 | ||
|
480c06f288 | ||
|
39c5860041 | ||
|
c9443b75f2 | ||
|
bae105dbc9 | ||
|
7ddc054890 | ||
|
916c0fb1da | ||
|
04c2118ed8 | ||
|
17b84c4f58 | ||
|
778faa1049 | ||
|
94e661c6b0 | ||
|
14ee1314de | ||
|
a333bc3860 | ||
|
9e14aff459 | ||
|
ba06bce930 | ||
|
561f185551 | ||
|
48cb001fb3 | ||
|
5da0690c5c | ||
|
8d605e99fa | ||
|
1aeeb6b932 | ||
|
f048730edd | ||
|
1b4f5b91aa | ||
|
6ea60a980b | ||
|
3d9c1406f7 | ||
|
5830ea7b82 | ||
|
cda59960b2 | ||
|
2e9c077535 | ||
|
a9cbc1740a | ||
|
dcca1b8737 | ||
|
6bd0af6c5a | ||
|
6ef86c3cb8 | ||
|
b91b22a983 | ||
|
63fec3d627 | ||
|
b50c20a5ed | ||
|
bb1980eb84 | ||
|
9922de378a | ||
|
1bb6889ba4 | ||
|
9756d15468 | ||
|
79bc9ffe24 | ||
|
7b19866d1b | ||
|
b549bdcec8 | ||
|
3c867a0252 | ||
|
71e6866701 | ||
|
28a781d511 | ||
|
43705fed86 | ||
|
69b342c504 | ||
|
ba0fa2e102 | ||
|
784a1a1c2b | ||
|
f1dd4462f2 | ||
|
c37ea38107 | ||
|
4b4f405a79 | ||
|
b1280eb65c | ||
|
0b02bf2331 | ||
|
42ccf1b050 | ||
|
c3ca4673d1 | ||
|
a66f84c0d5 | ||
|
061e3b252b | ||
|
f90a151150 | ||
|
ef45d94220 | ||
|
44abc1ce20 | ||
|
fe7f5a7630 | ||
|
8801f840d4 | ||
|
a92d680443 | ||
|
b4c48242cb | ||
|
313a6e4564 | ||
|
2680e4c45a |
100
.editorconfig
Normal file
100
.editorconfig
Normal file
@ -0,0 +1,100 @@
|
||||
# Remove the line below if you want to inherit .editorconfig settings from higher directories
|
||||
root = true
|
||||
|
||||
# C# files
|
||||
[*.cs]
|
||||
indent_style = tab
|
||||
indent_size = tab
|
||||
tab_size = 4
|
||||
|
||||
# New line preferences
|
||||
end_of_line = crlf
|
||||
insert_final_newline = true
|
||||
|
||||
|
||||
#### C# Coding Conventions ####
|
||||
|
||||
# Expression-bodied members
|
||||
csharp_style_expression_bodied_accessors = true:silent
|
||||
csharp_style_expression_bodied_constructors = false:silent
|
||||
csharp_style_expression_bodied_indexers = true:silent
|
||||
csharp_style_expression_bodied_lambdas = true:silent
|
||||
csharp_style_expression_bodied_local_functions = false:silent
|
||||
csharp_style_expression_bodied_methods = false:silent
|
||||
csharp_style_expression_bodied_operators = false:silent
|
||||
csharp_style_expression_bodied_properties = true:silent
|
||||
|
||||
# Pattern matching preferences
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||
csharp_style_prefer_not_pattern = true:suggestion
|
||||
csharp_style_prefer_pattern_matching = true:silent
|
||||
csharp_style_prefer_switch_expression = true:suggestion
|
||||
|
||||
# Null-checking preferences
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
|
||||
# Code-block preferences
|
||||
csharp_prefer_braces = true:silent
|
||||
|
||||
# Expression-level preferences
|
||||
csharp_prefer_simple_default_expression = true:suggestion
|
||||
csharp_style_deconstructed_variable_declaration = true:suggestion
|
||||
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:suggestion
|
||||
csharp_style_pattern_local_over_anonymous_function = true:suggestion
|
||||
csharp_style_prefer_index_operator = true:suggestion
|
||||
csharp_style_prefer_range_operator = true:suggestion
|
||||
csharp_style_throw_expression = true:suggestion
|
||||
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
|
||||
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
|
||||
|
||||
# 'using' directive preferences
|
||||
csharp_using_directive_placement = outside_namespace:silent
|
||||
|
||||
#### C# Formatting Rules ####
|
||||
|
||||
# New line preferences
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_between_query_expression_clauses = true
|
||||
|
||||
# Indentation preferences
|
||||
csharp_indent_block_contents = true
|
||||
csharp_indent_braces = false
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_case_contents_when_block = true
|
||||
csharp_indent_labels = no_change
|
||||
csharp_indent_switch_labels = true
|
||||
|
||||
# Space preferences
|
||||
csharp_space_after_cast = false
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
csharp_space_after_comma = true
|
||||
csharp_space_after_dot = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_after_semicolon_in_for_statement = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_around_declaration_statements = false
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_before_comma = false
|
||||
csharp_space_before_dot = false
|
||||
csharp_space_before_open_square_brackets = false
|
||||
csharp_space_before_semicolon_in_for_statement = false
|
||||
csharp_space_between_empty_square_brackets = false
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_between_method_call_parameter_list_parentheses = true
|
||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = true
|
||||
csharp_space_between_parentheses = control_flow_statements
|
||||
csharp_space_between_square_brackets = false
|
||||
|
||||
# Wrapping preferences
|
||||
csharp_preserve_single_line_blocks = true
|
||||
csharp_preserve_single_line_statements = true
|
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: garrynewman
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Set x to y
|
||||
2. Run for x minutes
|
||||
3. Call x
|
||||
4. See error
|
||||
|
||||
**Calling Code**
|
||||
```
|
||||
// The code you're using to call into Steamworks
|
||||
Steamworks.DoBug();
|
||||
```
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Unity: [e.g Unity 2019.3]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
10
.github/ISSUE_TEMPLATE/something-else.md
vendored
Normal file
10
.github/ISSUE_TEMPLATE/something-else.md
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
name: Something Else
|
||||
about: Describe this issue template's purpose here.
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
42
.github/workflows/dotnetcore.yml
vendored
Normal file
42
.github/workflows/dotnetcore.yml
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
name: Build All
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- name: Setup dotnet 6.0.x
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
with:
|
||||
dotnet-version: '6.0.x'
|
||||
include-prerelease: true
|
||||
|
||||
- name: Restore Win64
|
||||
run: dotnet restore Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj
|
||||
- name: Restore Win32
|
||||
run: dotnet restore Facepunch.Steamworks\Facepunch.Steamworks.Win32.csproj
|
||||
- name: Restore Posix
|
||||
run: dotnet restore Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj
|
||||
|
||||
- name: Build Win64
|
||||
run: dotnet build Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj
|
||||
- name: Build Win32
|
||||
run: dotnet build Facepunch.Steamworks\Facepunch.Steamworks.Win32.csproj
|
||||
- name: Build Posix
|
||||
run: dotnet build Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj
|
||||
|
||||
- name: Build Win64 Release
|
||||
run: dotnet build Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj --configuration Release
|
||||
- name: Build Win32 Release
|
||||
run: dotnet build Facepunch.Steamworks\Facepunch.Steamworks.Win32.csproj --configuration Release
|
||||
- name: Build Posix Release
|
||||
run: dotnet build Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj --configuration Release
|
||||
|
||||
- uses: actions/upload-artifact@v4.4.3
|
||||
with:
|
||||
name: Compiled Files
|
||||
path: Facepunch.Steamworks/bin
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -55,11 +55,14 @@ Facepunch.Steamworks.Test/bin/Release/Facepunch.Steamworks.Test.dll
|
||||
Facepunch.Steamworks.Test/bin/Release/Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll
|
||||
*.user
|
||||
*.cache
|
||||
*.idea
|
||||
*.vscode
|
||||
TestResults
|
||||
obj
|
||||
Facepunch.Steamworks/bin/Debug/Facepunch.Steamworks.Api.dll
|
||||
Facepunch.Steamworks/bin/Debug/Facepunch.Steamworks.dll
|
||||
Facepunch.Steamworks/bin/Release/Facepunch.Steamworks.dll
|
||||
Facepunch.Steamworks/bin
|
||||
*.opendb
|
||||
*.db
|
||||
Facepunch.Steamworks.dll
|
||||
@ -67,3 +70,8 @@ Facepunch.Steamworks.Test.dll
|
||||
*UnitTestFramework.dll
|
||||
mscorlib.dll
|
||||
*.nlp
|
||||
packages
|
||||
Generator/bin
|
||||
*.XML
|
||||
.vs
|
||||
Facepunch.Steamworks.Test/bin/**
|
||||
|
5
CompileFix.bat
Normal file
5
CompileFix.bat
Normal file
@ -0,0 +1,5 @@
|
||||
dotnet restore .\Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj
|
||||
dotnet restore .\Facepunch.Steamworks\Facepunch.Steamworks.Win32.csproj
|
||||
dotnet restore .\Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj
|
||||
dotnet restore .\Facepunch.Steamworks.Test\Facepunch.Steamworks.TestWin32.csproj
|
||||
dotnet restore .\Facepunch.Steamworks.Test\Facepunch.Steamworks.TestWin64.csproj
|
121
Facepunch.Steamworks.Test/AppTest.cs
Normal file
121
Facepunch.Steamworks.Test/AppTest.cs
Normal file
@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public class AppTest
|
||||
{
|
||||
[AssemblyInitialize]
|
||||
public static void AssemblyInit( TestContext context )
|
||||
{
|
||||
Steamworks.Dispatch.OnDebugCallback = ( type, str, server ) =>
|
||||
{
|
||||
Console.WriteLine( $"[Callback {type} {(server ? "server" : "client")}]" );
|
||||
Console.WriteLine( str );
|
||||
Console.WriteLine( $"" );
|
||||
};
|
||||
|
||||
Steamworks.Dispatch.OnException = ( e ) =>
|
||||
{
|
||||
Console.Error.WriteLine( e.Message );
|
||||
Console.Error.WriteLine( e.StackTrace );
|
||||
Assert.Fail( e.Message );
|
||||
};
|
||||
|
||||
//
|
||||
// Init Client
|
||||
//
|
||||
Steamworks.SteamClient.Init( 252490 );
|
||||
|
||||
//
|
||||
// Init Server
|
||||
//
|
||||
var serverInit = new SteamServerInit( "rust", "Rusty Mode" )
|
||||
{
|
||||
GamePort = 28015,
|
||||
Secure = true,
|
||||
QueryPort = 28016
|
||||
};
|
||||
|
||||
Steamworks.SteamServer.Init( 252490, serverInit );
|
||||
|
||||
//
|
||||
// Needs to happen before LogOnAnonymous
|
||||
//
|
||||
SteamNetworkingSockets.RequestFakeIP();
|
||||
|
||||
SteamServer.LogOnAnonymous();
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GameLangauge()
|
||||
{
|
||||
var gl = SteamApps.GameLanguage;
|
||||
Assert.IsNotNull( gl );
|
||||
Assert.IsTrue( gl.Length > 3 );
|
||||
|
||||
Console.WriteLine( $"{gl}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AppInstallDir()
|
||||
{
|
||||
var str = SteamApps.AppInstallDir();
|
||||
Assert.IsNotNull( str );
|
||||
Assert.IsTrue( str.Length > 3 );
|
||||
|
||||
Console.WriteLine( $"{str}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AppOwner()
|
||||
{
|
||||
var steamid = SteamApps.AppOwner;
|
||||
Assert.IsTrue( steamid.Value > 70561197960279927 );
|
||||
Assert.IsTrue( steamid.Value < 80561197960279927 );
|
||||
|
||||
Console.WriteLine( $"{steamid.Value}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void InstalledDepots()
|
||||
{
|
||||
var depots = SteamApps.InstalledDepots().ToArray();
|
||||
|
||||
Assert.IsNotNull( depots );
|
||||
Assert.IsTrue( depots.Length > 0 );
|
||||
|
||||
foreach ( var depot in depots )
|
||||
{
|
||||
Console.WriteLine( $"{depot.Value}" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetFileDetails()
|
||||
{
|
||||
var fileinfo = await SteamApps.GetFileDetailsAsync( "RustClient.exe" );
|
||||
|
||||
Console.WriteLine( $"fileinfo.SizeInBytes: {fileinfo?.SizeInBytes}" );
|
||||
Console.WriteLine( $"fileinfo.Sha1: {fileinfo?.Sha1}" );
|
||||
Console.WriteLine( $"fileinfo.Flags: {fileinfo?.Flags}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CommandLine()
|
||||
{
|
||||
var cl = SteamApps.CommandLine;
|
||||
|
||||
Console.WriteLine( $"CommandLine: {cl}" );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
59
Facepunch.Steamworks.Test/ClanTest.cs
Normal file
59
Facepunch.Steamworks.Test/ClanTest.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[DeploymentItem("steam_api64.dll")]
|
||||
[DeploymentItem("steam_api.dll")]
|
||||
[TestClass]
|
||||
public class ClanTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void GetName()
|
||||
{
|
||||
var clan = new Clan(103582791433666425);
|
||||
|
||||
Assert.AreEqual("Steamworks Development", clan.Name);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetClanTag()
|
||||
{
|
||||
var clan = new Clan(103582791433666425);
|
||||
|
||||
Assert.AreEqual("SteamworksDev", clan.Tag);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetOwner()
|
||||
{
|
||||
var clan = new Clan(103582791433666425);
|
||||
await clan.RequestOfficerList();
|
||||
|
||||
Assert.AreNotEqual(new SteamId(), clan.Owner.Id);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetOfficers()
|
||||
{
|
||||
var clan = new Clan(103582791433666425);
|
||||
foreach (var officer in clan.GetOfficers())
|
||||
{
|
||||
Console.WriteLine($"{officer.Name} : {officer.Id}");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task RequestOfficerList()
|
||||
{
|
||||
var clan = new Clan(103582791433666425);
|
||||
bool res = await clan.RequestOfficerList();
|
||||
|
||||
Assert.AreEqual(true, res);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,253 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Facepunch.Steamworks.Test
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( Config.LibraryName + ".dll" )]
|
||||
[DeploymentItem( "steam_appid.txt" )]
|
||||
public partial class Client
|
||||
{
|
||||
[TestMethod]
|
||||
public void Init()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Init_50()
|
||||
{
|
||||
for ( int i = 0; i < 50; i++ )
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Name()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var username = client.Username;
|
||||
Console.WriteLine( username );
|
||||
Assert.IsTrue( client.IsValid );
|
||||
Assert.IsNotNull( username );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SteamId()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var steamid = client.SteamId;
|
||||
Console.WriteLine( steamid );
|
||||
Assert.IsTrue( client.IsValid );
|
||||
Assert.AreNotEqual( 0, steamid );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AuthSessionTicket()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var ticket = client.Auth.GetAuthSessionTicket();
|
||||
|
||||
Assert.IsTrue( ticket != null );
|
||||
Assert.IsTrue( ticket.Handle != 0 );
|
||||
Assert.IsTrue( ticket.Data.Length > 0 );
|
||||
|
||||
ticket.Cancel();
|
||||
|
||||
Assert.IsTrue( ticket.Handle == 0 );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void VoiceOptimalSampleRate()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var rate = client.Voice.OptimalSampleRate;
|
||||
Assert.AreNotEqual( rate, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Update()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
for( int i=0; i<1024; i++ )
|
||||
{
|
||||
client.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static MemoryStream decompressStream = new MemoryStream();
|
||||
|
||||
[TestMethod]
|
||||
public void GetVoice()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
int unCompressed = 0;
|
||||
int compressed = 0;
|
||||
|
||||
client.Voice.OnCompressedData = ( ptr, length ) =>
|
||||
{
|
||||
compressed += length;
|
||||
|
||||
if ( !client.Voice.Decompress( ptr, 0, length, decompressStream ) )
|
||||
{
|
||||
Assert.Fail( "Decompress returned false" );
|
||||
}
|
||||
};
|
||||
|
||||
client.Voice.OnUncompressedData = ( ptr, length ) =>
|
||||
{
|
||||
unCompressed += length;
|
||||
};
|
||||
|
||||
client.Voice.WantsRecording = true;
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
|
||||
while ( sw.Elapsed.TotalSeconds < 3 )
|
||||
{
|
||||
client.Update();
|
||||
System.Threading.Thread.Sleep( 10 );
|
||||
}
|
||||
|
||||
Assert.AreNotEqual( unCompressed, 0 );
|
||||
Assert.AreNotEqual( compressed, 0 );
|
||||
|
||||
// Should really be > 0 if the mic was getting audio
|
||||
Console.WriteLine( "unCompressed: {0}", unCompressed );
|
||||
Console.WriteLine( "compressed: {0}", compressed );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetVoice_Compressed_Only()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
int compressed = 0;
|
||||
|
||||
client.Voice.OnCompressedData = ( ptr, length ) =>
|
||||
{
|
||||
compressed += length;
|
||||
};
|
||||
|
||||
client.Voice.WantsRecording = true;
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
|
||||
while ( sw.Elapsed.TotalSeconds < 3 )
|
||||
{
|
||||
client.Update();
|
||||
System.Threading.Thread.Sleep( 10 );
|
||||
}
|
||||
|
||||
Assert.AreNotEqual( compressed, 0 );
|
||||
Console.WriteLine( "compressed: {0}", compressed );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetVoice_UnCompressed_Only()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
int unCompressed = 0;
|
||||
|
||||
client.Voice.OnUncompressedData = ( ptr, length ) =>
|
||||
{
|
||||
unCompressed += length;
|
||||
};
|
||||
|
||||
client.Voice.WantsRecording = true;
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
|
||||
while ( sw.Elapsed.TotalSeconds < 3 )
|
||||
{
|
||||
client.Update();
|
||||
System.Threading.Thread.Sleep( 10 );
|
||||
}
|
||||
|
||||
Assert.AreNotEqual( unCompressed, 0 );
|
||||
|
||||
// Should really be > 0 if the mic was getting audio
|
||||
Console.WriteLine( "unCompressed: {0}", unCompressed );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void InventoryDefinitions()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsNotNull( client.Inventory.Definitions );
|
||||
Assert.AreNotEqual( 0, client.Inventory.Definitions.Length );
|
||||
|
||||
foreach ( var i in client.Inventory.Definitions )
|
||||
{
|
||||
Console.WriteLine( "{0}: {1}", i.Id, i.Name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void InventoryItemList()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
bool CallbackCalled = false;
|
||||
|
||||
// OnUpdate hsould be called when we receive a list of our items
|
||||
client.Inventory.OnUpdate = () => { CallbackCalled = true; };
|
||||
|
||||
// tell steam to download the items
|
||||
client.Inventory.Refresh();
|
||||
|
||||
// Wait for the items
|
||||
var timeout = Stopwatch.StartNew();
|
||||
while ( client.Inventory.Items == null )
|
||||
{
|
||||
client.Update();
|
||||
System.Threading.Thread.Sleep( 1000 );
|
||||
|
||||
if ( timeout.Elapsed.TotalSeconds > 5 )
|
||||
break;
|
||||
}
|
||||
|
||||
// make sure callback was called
|
||||
Assert.IsTrue( CallbackCalled );
|
||||
|
||||
// Make sure items are valid
|
||||
foreach ( var item in client.Inventory.Items )
|
||||
{
|
||||
Assert.IsNotNull( item );
|
||||
Assert.IsNotNull( item.Definition );
|
||||
|
||||
Console.WriteLine( item.Definition.Name + " - " + item.Id );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Linq;
|
||||
|
||||
namespace Facepunch.Steamworks.Test
|
||||
{
|
||||
[DeploymentItem( Config.LibraryName + ".dll" )]
|
||||
[DeploymentItem( "steam_appid.txt" )]
|
||||
[TestClass]
|
||||
public class Friends
|
||||
{
|
||||
[TestMethod]
|
||||
public void FriendList()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
|
||||
client.Friends.Refresh();
|
||||
|
||||
Assert.IsNotNull( client.Friends.All );
|
||||
|
||||
foreach ( var friend in client.Friends.All )
|
||||
{
|
||||
Console.WriteLine( "{0}: {1} (Friend:{2}) (Blocked:{3})", friend.Id, friend.Name, friend.IsFriend, friend.IsBlocked );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void FriendListWithoutRefresh()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
|
||||
foreach ( var friend in client.Friends.All )
|
||||
{
|
||||
Console.WriteLine( "{0}: {1} (Friend:{2}) (Blocked:{3})", friend.Id, friend.Name, friend.IsFriend, friend.IsBlocked );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Avatar()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
|
||||
var friend = client.Friends.All.First();
|
||||
|
||||
var img = client.Friends.GetAvatar( Steamworks.Friends.AvatarSize.Medium, friend.Id );
|
||||
|
||||
Assert.AreEqual( img.Width, 64 );
|
||||
Assert.AreEqual( img.Height, 64 );
|
||||
|
||||
while ( !img.IsLoaded && !img.IsError )
|
||||
{
|
||||
client.Update();
|
||||
System.Threading.Thread.Sleep( 10 );
|
||||
}
|
||||
|
||||
Assert.AreEqual( img.Data.Length, img.Width * img.Height * 4 );
|
||||
|
||||
DrawImage( img );
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawImage( Image img )
|
||||
{
|
||||
var grad = " -:+#";
|
||||
|
||||
for ( int y = 0; y<img.Height; y++ )
|
||||
{
|
||||
var str = "";
|
||||
|
||||
for ( int x = 0; x < img.Width; x++ )
|
||||
{
|
||||
var p = img.GetPixel( x, y );
|
||||
|
||||
var brightness = 1 - ((float)(p.r + p.g + p.b) / (255.0f * 3.0f));
|
||||
var c = (int) ((grad.Length) * brightness);
|
||||
str += grad[c];
|
||||
|
||||
}
|
||||
|
||||
Console.WriteLine( str );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Facepunch.Steamworks.Test
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( Config.LibraryName + ".dll" )]
|
||||
[DeploymentItem( "steam_appid.txt" )]
|
||||
public partial class Networking
|
||||
{
|
||||
[TestMethod]
|
||||
public void PeerToPeerSend()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var TestString = "This string will be transformed to bytes, sent over the Steam P2P network, then converted back to a string.";
|
||||
var OutputReceived = false;
|
||||
var data = Encoding.UTF8.GetBytes( TestString );
|
||||
|
||||
client.Networking.OnP2PData = ( steamid, ms, channel ) =>
|
||||
{
|
||||
var str = Encoding.UTF8.GetString( ms.GetBuffer() );
|
||||
Assert.AreEqual( str, TestString );
|
||||
Assert.AreEqual( steamid, client.SteamId );
|
||||
OutputReceived = true;
|
||||
};
|
||||
|
||||
client.Networking.OnIncomingConnection = ( steamid ) =>
|
||||
{
|
||||
Console.WriteLine( "Incoming P2P Connection: " + steamid );
|
||||
return true;
|
||||
};
|
||||
|
||||
client.Networking.OnConnectionFailed = ( steamid, error ) =>
|
||||
{
|
||||
Console.WriteLine( "Connection Error: " + steamid + " - " + error );
|
||||
};
|
||||
|
||||
client.Networking.SendP2PPacket( client.SteamId, data, data.Length );
|
||||
|
||||
while( true )
|
||||
{
|
||||
Thread.Sleep( 10 );
|
||||
client.Update();
|
||||
|
||||
if ( OutputReceived )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PeerToPeerFailure()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var TestString = "This string will be transformed to bytes, sent over the Steam P2P network, then converted back to a string.";
|
||||
var TimeoutReceived = false;
|
||||
var data = Encoding.UTF8.GetBytes( TestString );
|
||||
|
||||
client.Networking.OnIncomingConnection = ( steamid ) =>
|
||||
{
|
||||
Console.WriteLine( "Incoming P2P Connection: " + steamid );
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
client.Networking.OnConnectionFailed = ( steamid, error ) =>
|
||||
{
|
||||
Console.WriteLine( "Connection Error: " + steamid + " - " + error );
|
||||
TimeoutReceived = true;
|
||||
};
|
||||
|
||||
ulong rand = (ulong) new Random().Next( 1024 * 16 );
|
||||
|
||||
// Send to an invalid, not listening steamid
|
||||
if ( !client.Networking.SendP2PPacket( client.SteamId + rand, data, data.Length ) )
|
||||
{
|
||||
Console.WriteLine( "Couldn't send packet" );
|
||||
return;
|
||||
}
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
|
||||
while ( true )
|
||||
{
|
||||
Thread.Sleep( 10 );
|
||||
client.Update();
|
||||
|
||||
//
|
||||
// Timout is usually around 15 seconds
|
||||
//
|
||||
if ( TimeoutReceived )
|
||||
break;
|
||||
|
||||
if ( sw.Elapsed.TotalSeconds > 30 )
|
||||
{
|
||||
Assert.Fail( "Didn't time out" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
43
Facepunch.Steamworks.Test/Client/Server/StatsTest.cs
Normal file
43
Facepunch.Steamworks.Test/Client/Server/StatsTest.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
/*
|
||||
namespace Facepunch.Steamworks.Test
|
||||
{
|
||||
public partial class Server
|
||||
{
|
||||
[TestMethod]
|
||||
public void StatsGet()
|
||||
{
|
||||
using ( var server = new Facepunch.Steamworks.Server( 252490, new ServerInit( "rust", "Rust" ) ) )
|
||||
{
|
||||
Assert.IsTrue( server.IsValid );
|
||||
server.LogOnAnonymous();
|
||||
|
||||
ulong MySteamId = 76561197960279927;
|
||||
|
||||
bool GotStats = false;
|
||||
|
||||
server.Stats.Refresh( MySteamId, (steamid, success) =>
|
||||
{
|
||||
GotStats = true;
|
||||
Assert.IsTrue( success );
|
||||
|
||||
var deathsInCallback = server.Stats.GetInt( MySteamId, "deaths", -1 );
|
||||
Console.WriteLine( "deathsInCallback: {0}", deathsInCallback );
|
||||
Assert.IsTrue( deathsInCallback > 0 );
|
||||
} );
|
||||
|
||||
|
||||
server.UpdateWhile( () => !GotStats );
|
||||
|
||||
var deaths = server.Stats.GetInt( MySteamId, "deaths", -1 );
|
||||
Console.WriteLine( "deathsInCallback: {0}", deaths );
|
||||
Assert.IsTrue( deaths > 0 );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
@ -1,357 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Facepunch.Steamworks.Test
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( Config.LibraryName + ".dll" )]
|
||||
[DeploymentItem( "steam_appid.txt" )]
|
||||
public partial class ServerList
|
||||
{
|
||||
[TestMethod]
|
||||
public void InternetList()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var filter = new Facepunch.Steamworks.ServerList.Filter();
|
||||
filter.Add( "appid", client.AppId.ToString() );
|
||||
filter.Add( "gamedir", "rust" );
|
||||
filter.Add( "secure", "1" );
|
||||
|
||||
var query = client.ServerList.Internet( filter );
|
||||
|
||||
for ( int i = 0; i < 1000; i++ )
|
||||
{
|
||||
client.Update();
|
||||
System.Threading.Thread.Sleep( 10 );
|
||||
|
||||
foreach ( var s in query.Responded )
|
||||
{
|
||||
Assert.AreEqual( s.AppId, client.AppId );
|
||||
Assert.AreEqual( s.GameDir, "rust" );
|
||||
}
|
||||
|
||||
if ( query.Finished )
|
||||
break;
|
||||
}
|
||||
|
||||
Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
|
||||
Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
|
||||
|
||||
foreach ( var server in query.Responded.Take( 20 ) )
|
||||
{
|
||||
Console.WriteLine( "{0} {1}", server.AddressString, server.Name );
|
||||
}
|
||||
|
||||
query.Dispose();
|
||||
|
||||
for ( int i = 0; i < 100; i++ )
|
||||
{
|
||||
client.Update();
|
||||
System.Threading.Thread.Sleep( 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void MultipleInternetList()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var queries = new List<Facepunch.Steamworks.ServerList.Request>();
|
||||
|
||||
var filter = new Facepunch.Steamworks.ServerList.Filter();
|
||||
filter.Add( "map", "barren" );
|
||||
|
||||
for ( int i = 0; i < 10; i++ )
|
||||
queries.Add( client.ServerList.Internet( filter ) );
|
||||
|
||||
for ( int i = 0; i < 100; i++ )
|
||||
{
|
||||
client.Update();
|
||||
System.Threading.Thread.Sleep( 5 );
|
||||
|
||||
if ( queries.Any( x => x.Finished ) )
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ( var query in queries )
|
||||
{
|
||||
Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
|
||||
Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
|
||||
|
||||
client.Update();
|
||||
query.Dispose();
|
||||
client.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Filters()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var filter = new Facepunch.Steamworks.ServerList.Filter();
|
||||
filter.Add( "map", "barren" );
|
||||
|
||||
|
||||
var query = client.ServerList.Internet( filter );
|
||||
|
||||
while ( true )
|
||||
{
|
||||
client.Update();
|
||||
System.Threading.Thread.Sleep( 2 );
|
||||
|
||||
if ( query.Finished )
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ( var x in query.Responded )
|
||||
{
|
||||
Assert.AreEqual( x.Map.ToLower(), "barren" );
|
||||
}
|
||||
|
||||
query.Dispose();
|
||||
|
||||
for ( int i = 0; i < 100; i++ )
|
||||
{
|
||||
client.Update();
|
||||
System.Threading.Thread.Sleep( 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void HistoryList()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var query = client.ServerList.History();
|
||||
|
||||
while ( true )
|
||||
{
|
||||
client.Update();
|
||||
System.Threading.Thread.Sleep( 2 );
|
||||
|
||||
if ( query.Finished )
|
||||
break;
|
||||
}
|
||||
|
||||
Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
|
||||
Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
|
||||
|
||||
foreach ( var x in query.Responded )
|
||||
{
|
||||
Console.WriteLine( x.Map );
|
||||
}
|
||||
|
||||
query.Dispose();
|
||||
|
||||
for ( int i = 0; i < 100; i++ )
|
||||
{
|
||||
client.Update();
|
||||
System.Threading.Thread.Sleep( 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CustomList()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var servers = new List<string>();
|
||||
|
||||
servers.Add( "158.85.101.20:28015" );
|
||||
servers.Add( "158.85.101.20:28022" );
|
||||
servers.Add( "173.192.176.171:28615" );
|
||||
servers.Add( "109.95.212.35:28215" );
|
||||
servers.Add( "109.95.212.35:28115" );
|
||||
servers.Add( "27.50.72.176:28015" );
|
||||
servers.Add( "109.95.212.40:28015" );
|
||||
servers.Add( "212.38.168.149:28215" );
|
||||
servers.Add( "27.50.72.167:28215" );
|
||||
servers.Add( "85.236.105.7:28215" );
|
||||
servers.Add( "107.182.233.216:28215" );
|
||||
servers.Add( "85.236.105.11:28215" );
|
||||
servers.Add( "109.95.211.198:28215" );
|
||||
servers.Add( "8.26.94.190:28015" );
|
||||
servers.Add( "221.121.151.37:28215" );
|
||||
servers.Add( "161.202.144.216:28215" );
|
||||
servers.Add( "107.182.230.181:28215" );
|
||||
servers.Add( "107.182.231.134:27101" );
|
||||
servers.Add( "107.182.233.181:27101" );
|
||||
servers.Add( "78.129.153.47:27101" );
|
||||
servers.Add( "109.95.211.206:27101" );
|
||||
servers.Add( "169.57.142.73:27101" );
|
||||
servers.Add( "221.121.154.147:27101" );
|
||||
servers.Add( "31.216.52.44:30015" );
|
||||
servers.Add( "109.169.94.17:28215" );
|
||||
servers.Add( "109.169.94.17:28315" );
|
||||
servers.Add( "109.169.94.17:28015" );
|
||||
servers.Add( "41.0.11.167:27141" );
|
||||
servers.Add( "78.129.153.47:27131" );
|
||||
servers.Add( "109.95.211.206:27111" );
|
||||
servers.Add( "107.182.231.134:27111" );
|
||||
servers.Add( "198.27.70.162:28015" );
|
||||
servers.Add( "198.27.70.162:28215" );
|
||||
servers.Add( "198.27.70.162:28115" );
|
||||
servers.Add( "169.57.142.73:27111" );
|
||||
servers.Add( "221.121.154.147:27111" );
|
||||
servers.Add( "107.182.233.181:27111" );
|
||||
servers.Add( "78.129.153.47:27111" );
|
||||
servers.Add( "109.95.211.215:28015" );
|
||||
servers.Add( "50.23.131.208:28015" );
|
||||
servers.Add( "50.23.131.208:28115" );
|
||||
servers.Add( "50.23.131.208:28215" );
|
||||
servers.Add( "63.251.114.37:28215" );
|
||||
servers.Add( "63.251.114.37:28115" );
|
||||
servers.Add( "63.251.114.37:28015" );
|
||||
servers.Add( "149.202.89.85:27101" );
|
||||
servers.Add( "149.202.89.85:27111" );
|
||||
servers.Add( "149.202.89.85:27131" );
|
||||
servers.Add( "8.26.94.147:27101" );
|
||||
servers.Add( "8.26.94.147:27111" );
|
||||
servers.Add( "8.26.94.147:27121" );
|
||||
servers.Add( "159.8.147.197:28025" );
|
||||
servers.Add( "162.248.88.203:27038" );
|
||||
servers.Add( "162.248.88.203:28091" );
|
||||
servers.Add( "74.91.119.142:28069" );
|
||||
servers.Add( "162.248.88.203:25063" );
|
||||
servers.Add( "64.251.7.189:28115" );
|
||||
servers.Add( "64.251.7.189:28015" );
|
||||
servers.Add( "216.52.0.170:28215" );
|
||||
servers.Add( "217.147.91.80:28215" );
|
||||
servers.Add( "63.251.112.121:28215" );
|
||||
servers.Add( "162.248.88.203:28074" );
|
||||
servers.Add( "74.91.119.142:27095" );
|
||||
servers.Add( "95.172.92.176:28065" );
|
||||
servers.Add( "192.223.26.55:26032" );
|
||||
servers.Add( "40.114.199.6:28085" );
|
||||
servers.Add( "95.172.92.176:27095" );
|
||||
servers.Add( "216.52.0.172:28015" );
|
||||
servers.Add( "216.52.0.171:28115" );
|
||||
servers.Add( "27.50.72.179:28015" );
|
||||
servers.Add( "27.50.72.180:28115" );
|
||||
servers.Add( "221.121.158.203:28015" );
|
||||
servers.Add( "63.251.242.246:28015" );
|
||||
servers.Add( "85.236.105.51:28015" );
|
||||
servers.Add( "85.236.105.47:28015" );
|
||||
servers.Add( "209.95.60.216:28015" );
|
||||
servers.Add( "212.38.168.14:28015" );
|
||||
servers.Add( "217.147.91.138:28015" );
|
||||
servers.Add( "31.216.52.42:28015" );
|
||||
servers.Add( "107.182.226.225:28015" );
|
||||
servers.Add( "109.95.211.69:28015" );
|
||||
servers.Add( "209.95.56.13:28015" );
|
||||
servers.Add( "173.244.192.101:28015" );
|
||||
servers.Add( "221.121.158.201:28115" );
|
||||
servers.Add( "63.251.242.245:28115" );
|
||||
servers.Add( "85.236.105.50:28115" );
|
||||
servers.Add( "85.236.105.46:28115" );
|
||||
servers.Add( "209.95.60.217:28115" );
|
||||
servers.Add( "212.38.168.13:28115" );
|
||||
servers.Add( "217.147.91.139:28115" );
|
||||
servers.Add( "107.182.226.224:28115" );
|
||||
servers.Add( "109.95.211.14:28115" );
|
||||
servers.Add( "109.95.211.16:28115" );
|
||||
servers.Add( "109.95.211.17:28115" );
|
||||
servers.Add( "209.95.56.14:28115" );
|
||||
servers.Add( "173.244.192.100:28115" );
|
||||
servers.Add( "209.95.60.218:28215" );
|
||||
servers.Add( "109.95.211.13:28215" );
|
||||
servers.Add( "109.95.211.15:28215" );
|
||||
servers.Add( "31.216.52.41:29015" );
|
||||
|
||||
var query = client.ServerList.Custom( servers );
|
||||
|
||||
for ( int i = 0; i < 1000; i++ )
|
||||
{
|
||||
client.Update();
|
||||
System.Threading.Thread.Sleep( 20 );
|
||||
|
||||
if ( query.Finished )
|
||||
break;
|
||||
}
|
||||
|
||||
Console.WriteLine( "Responded: " + query.Responded.Count.ToString() );
|
||||
Console.WriteLine( "Unresponsive: " + query.Unresponsive.Count.ToString() );
|
||||
|
||||
foreach ( var s in query.Responded )
|
||||
{
|
||||
Console.WriteLine( "{0} - {1}", s.AddressString, s.Name );
|
||||
}
|
||||
|
||||
query.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Rules()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var filter = new Facepunch.Steamworks.ServerList.Filter();
|
||||
filter.Add( "appid", client.AppId.ToString() );
|
||||
filter.Add( "gamedir", "rust" );
|
||||
filter.Add( "secure", "1" );
|
||||
|
||||
using ( var query = client.ServerList.Internet( filter ) )
|
||||
{
|
||||
|
||||
for ( int i = 0; i < 1000; i++ )
|
||||
{
|
||||
GC.Collect();
|
||||
client.Update();
|
||||
GC.Collect();
|
||||
System.Threading.Thread.Sleep( 10 );
|
||||
|
||||
if ( query.Responded.Count > 20 )
|
||||
break;
|
||||
|
||||
if ( query.Finished )
|
||||
break;
|
||||
}
|
||||
|
||||
query.Dispose();
|
||||
|
||||
foreach ( var server in query.Responded.Take( 20 ) )
|
||||
{
|
||||
GC.Collect();
|
||||
server.FetchRules();
|
||||
GC.Collect();
|
||||
|
||||
int i = 0;
|
||||
while ( !server.HasRules )
|
||||
{
|
||||
i++;
|
||||
GC.Collect();
|
||||
client.Update();
|
||||
GC.Collect();
|
||||
System.Threading.Thread.Sleep( 2 );
|
||||
|
||||
if ( i > 100 )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( server.HasRules )
|
||||
{
|
||||
foreach ( var rule in server.Rules )
|
||||
{
|
||||
Console.WriteLine( rule.Key + " = " + rule.Value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Facepunch.Steamworks.Test
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( Config.LibraryName + ".dll" )]
|
||||
[DeploymentItem( "steam_appid.txt" )]
|
||||
public class Stats
|
||||
{
|
||||
[TestMethod]
|
||||
public void UpdateStats()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
client.Stats.UpdateStats();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UpdateSUpdateGlobalStatstats()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
client.Stats.UpdateGlobalStats( 1 );
|
||||
client.Stats.UpdateGlobalStats( 3 );
|
||||
client.Stats.UpdateGlobalStats( 7 );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetClientFloat()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var v = client.Stats.GetFloat( "deaths" );
|
||||
Console.WriteLine( v );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetClientInt()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var v = client.Stats.GetInt( "deaths" );
|
||||
Console.WriteLine( v );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetGlobalFloat()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var v = client.Stats.GetGlobalFloat( "deaths" );
|
||||
Console.WriteLine( v );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetGlobalInt()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
var v = client.Stats.GetGlobalInt( "deaths" );
|
||||
Console.WriteLine( v );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,425 +0,0 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Linq;
|
||||
|
||||
namespace Facepunch.Steamworks.Test
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( Config.LibraryName + ".dll" )]
|
||||
[DeploymentItem( "steam_appid.txt" )]
|
||||
public class WorkshopTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void Query()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
|
||||
var Query = client.Workshop.CreateQuery();
|
||||
|
||||
Query.Run();
|
||||
|
||||
// Block, wait for result
|
||||
// (don't do this in realtime)
|
||||
Query.Block();
|
||||
|
||||
Assert.IsFalse( Query.IsRunning );
|
||||
Assert.IsTrue( Query.TotalResults > 0 );
|
||||
Assert.IsTrue( Query.Items.Length > 0 );
|
||||
|
||||
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||
|
||||
// results
|
||||
|
||||
Console.WriteLine( "Searching" );
|
||||
|
||||
Query.Order = Workshop.Order.RankedByTextSearch;
|
||||
Query.QueryType = Workshop.QueryType.MicrotransactionItems;
|
||||
Query.SearchText = "black";
|
||||
Query.RequireTags.Add( "LongTShirt Skin" );
|
||||
Query.Run();
|
||||
|
||||
// Block, wait for result
|
||||
// (don't do this in realtime)
|
||||
Query.Block();
|
||||
|
||||
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||
|
||||
Assert.IsTrue( Query.TotalResults > 0 );
|
||||
Assert.IsTrue( Query.Items.Length > 0 );
|
||||
|
||||
foreach ( var item in Query.Items )
|
||||
{
|
||||
Console.WriteLine( "{0}", item.Title );
|
||||
Console.WriteLine( "\t WebsiteViews: {0}", item.WebsiteViews );
|
||||
Console.WriteLine( "\t VotesUp: {0}", item.VotesUp );
|
||||
Console.WriteLine( "\t PreviewUrl: {0}", item.PreviewImageUrl );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void QueryTagRequire()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
|
||||
using ( var Query = client.Workshop.CreateQuery() )
|
||||
{
|
||||
Query.RequireTags.Add( "LongTShirt Skin" );
|
||||
Query.Run();
|
||||
|
||||
Query.Block();
|
||||
|
||||
Assert.IsFalse( Query.IsRunning );
|
||||
Assert.IsTrue( Query.TotalResults > 0 );
|
||||
Assert.IsTrue( Query.Items.Length > 0 );
|
||||
|
||||
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||
|
||||
Assert.IsTrue( Query.TotalResults > 0 );
|
||||
Assert.IsTrue( Query.Items.Length > 0 );
|
||||
|
||||
foreach ( var item in Query.Items )
|
||||
{
|
||||
Console.WriteLine( "{0}", item.Title );
|
||||
Console.WriteLine( "\t{0}", string.Join( ";", item.Tags ) );
|
||||
|
||||
Assert.IsTrue( item.Tags.Contains( "LongTShirt Skin" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void QueryTagRequireMultiple()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
|
||||
using ( var Query = client.Workshop.CreateQuery() )
|
||||
{
|
||||
Query.RequireTags.Add( "LongTShirt Skin" );
|
||||
Query.RequireTags.Add( "version2" );
|
||||
Query.RequireAllTags = true;
|
||||
Query.Run();
|
||||
|
||||
Query.Block();
|
||||
|
||||
Assert.IsFalse( Query.IsRunning );
|
||||
Assert.IsTrue( Query.TotalResults > 0 );
|
||||
Assert.IsTrue( Query.Items.Length > 0 );
|
||||
|
||||
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||
|
||||
Assert.IsTrue( Query.TotalResults > 0 );
|
||||
Assert.IsTrue( Query.Items.Length > 0 );
|
||||
|
||||
foreach ( var item in Query.Items )
|
||||
{
|
||||
Console.WriteLine( "{0}", item.Title );
|
||||
Console.WriteLine( "\t{0}", string.Join( ";", item.Tags ) );
|
||||
|
||||
Assert.IsTrue( item.Tags.Contains( "LongTShirt Skin" ) );
|
||||
Assert.IsTrue( item.Tags.Contains( "version2" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void QueryTagExclude()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
|
||||
using ( var Query = client.Workshop.CreateQuery() )
|
||||
{
|
||||
Query.RequireTags.Add( "LongTShirt Skin" );
|
||||
Query.ExcludeTags.Add( "version2" );
|
||||
Query.Run();
|
||||
|
||||
Query.Block();
|
||||
|
||||
Assert.IsFalse( Query.IsRunning );
|
||||
Assert.IsTrue( Query.TotalResults > 0 );
|
||||
Assert.IsTrue( Query.Items.Length > 0 );
|
||||
|
||||
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||
|
||||
Assert.IsTrue( Query.TotalResults > 0 );
|
||||
Assert.IsTrue( Query.Items.Length > 0 );
|
||||
|
||||
foreach ( var item in Query.Items )
|
||||
{
|
||||
Console.WriteLine( "{0}", item.Title );
|
||||
Console.WriteLine( "\t{0}", string.Join( ";", item.Tags ) );
|
||||
|
||||
Assert.IsTrue( item.Tags.Contains( "LongTShirt Skin" ) );
|
||||
Assert.IsFalse( item.Tags.Contains( "version2" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void QueryFile()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
|
||||
using ( var Query = client.Workshop.CreateQuery() )
|
||||
{
|
||||
Query.FileId.Add( 751993251 );
|
||||
Query.Run();
|
||||
|
||||
Assert.IsTrue( Query.IsRunning );
|
||||
|
||||
Query.Block();
|
||||
|
||||
Assert.IsFalse( Query.IsRunning );
|
||||
Assert.AreEqual( Query.TotalResults, 1 );
|
||||
Assert.AreEqual( Query.Items.Length, 1 );
|
||||
|
||||
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||
|
||||
Assert.AreEqual<ulong>( Query.Items[0].Id, 751993251 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void QueryFiles()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
|
||||
using ( var Query = client.Workshop.CreateQuery() )
|
||||
{
|
||||
Query.FileId.Add( 751993251 );
|
||||
Query.FileId.Add( 747266909 );
|
||||
Query.Run();
|
||||
|
||||
Assert.IsTrue( Query.IsRunning );
|
||||
|
||||
Query.Block();
|
||||
|
||||
Assert.IsFalse( Query.IsRunning );
|
||||
Assert.AreEqual( Query.TotalResults, 2 );
|
||||
Assert.AreEqual( Query.Items.Length, 2 );
|
||||
|
||||
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||
|
||||
Assert.IsTrue( Query.Items.Any( x => x.Id == 751993251 ) );
|
||||
Assert.IsTrue( Query.Items.Any( x => x.Id == 747266909 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Query_255()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
|
||||
using ( var Query = client.Workshop.CreateQuery() )
|
||||
{
|
||||
Query.PerPage = 255;
|
||||
Query.Run();
|
||||
|
||||
Assert.IsTrue( Query.IsRunning );
|
||||
|
||||
Query.Block();
|
||||
|
||||
Assert.IsFalse( Query.IsRunning );
|
||||
Assert.AreEqual( Query.Items.Length, 255 );
|
||||
|
||||
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Query_28()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
|
||||
using ( var Query = client.Workshop.CreateQuery() )
|
||||
{
|
||||
Query.PerPage = 28;
|
||||
Query.Run();
|
||||
Query.Block();
|
||||
|
||||
var firstPage = Query.Items;
|
||||
Assert.AreEqual( firstPage.Length, 28 );
|
||||
|
||||
Console.WriteLine( "Page 2" );
|
||||
Query.Page++;
|
||||
Query.Run();
|
||||
Query.Block();
|
||||
|
||||
|
||||
var secondPage = Query.Items;
|
||||
Assert.AreEqual( secondPage.Length, 28 );
|
||||
|
||||
Console.WriteLine( "Page 3" );
|
||||
Query.Page++;
|
||||
Query.Run();
|
||||
Query.Block();
|
||||
|
||||
var thirdPage = Query.Items;
|
||||
Assert.AreEqual( thirdPage.Length, 28 );
|
||||
|
||||
foreach ( var i in firstPage )
|
||||
{
|
||||
Assert.IsFalse( secondPage.Any( x => x.Id == i.Id ) );
|
||||
Assert.IsFalse( thirdPage.Any( x => x.Id == i.Id ) );
|
||||
}
|
||||
|
||||
foreach ( var i in secondPage )
|
||||
{
|
||||
Assert.IsFalse( firstPage.Any( x => x.Id == i.Id ) );
|
||||
Assert.IsFalse( thirdPage.Any( x => x.Id == i.Id ) );
|
||||
}
|
||||
|
||||
foreach ( var i in thirdPage )
|
||||
{
|
||||
Assert.IsFalse( secondPage.Any( x => x.Id == i.Id ) );
|
||||
Assert.IsFalse( firstPage.Any( x => x.Id == i.Id ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DownloadFile()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
|
||||
using ( var Query = client.Workshop.CreateQuery() )
|
||||
{
|
||||
Query.FileId.Add( 661319648 );
|
||||
Query.Run();
|
||||
|
||||
Assert.IsTrue( Query.IsRunning );
|
||||
|
||||
Query.Block();
|
||||
|
||||
Assert.IsFalse( Query.IsRunning );
|
||||
Assert.AreEqual( Query.TotalResults, 1 );
|
||||
Assert.AreEqual( Query.Items.Length, 1 );
|
||||
|
||||
var item = Query.Items[0];
|
||||
|
||||
if ( !item.Installed )
|
||||
{
|
||||
item.Download();
|
||||
|
||||
while ( item.Downloading )
|
||||
{
|
||||
Thread.Sleep( 500 );
|
||||
client.Update();
|
||||
Console.WriteLine( "Download Progress: {0}", item.DownloadProgress );
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsNotNull( item.Directory );
|
||||
Assert.AreNotEqual( 0, item.Size );
|
||||
|
||||
Console.WriteLine( "item.Installed: {0}", item.Installed );
|
||||
Console.WriteLine( "item.Downloading: {0}", item.Downloading );
|
||||
Console.WriteLine( "item.DownloadPending: {0}", item.DownloadPending );
|
||||
Console.WriteLine( "item.Directory: {0}", item.Directory );
|
||||
Console.WriteLine( "item.Size: {0}mb", (item.Size / 1024 / 1024) );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory( "Run Manually" )]
|
||||
public void CreatePublish()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
|
||||
var item = client.Workshop.CreateItem( Workshop.ItemType.Microtransaction );
|
||||
|
||||
item.Title = "Facepunch.Steamworks Unit test";
|
||||
item.Tags.Add( "Apple" );
|
||||
item.Tags.Add( "Banana" );
|
||||
item.Publish();
|
||||
|
||||
while ( item.Publishing )
|
||||
{
|
||||
client.Update();
|
||||
Thread.Sleep( 100 );
|
||||
}
|
||||
|
||||
Assert.IsFalse( item.Publishing );
|
||||
Assert.AreNotEqual( 0, item.Id );
|
||||
Assert.IsNull( item.Error );
|
||||
|
||||
Console.WriteLine( "item.Id: {0}", item.Id );
|
||||
|
||||
item.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UserQuery()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
|
||||
var Query = client.Workshop.CreateQuery();
|
||||
|
||||
Query.UserId = 76561197960279927;
|
||||
Query.UserQueryType = Workshop.UserQueryType.Published;
|
||||
|
||||
Query.Run();
|
||||
|
||||
// Block, wait for result
|
||||
// (don't do this in realtime)
|
||||
Query.Block();
|
||||
|
||||
Assert.IsFalse( Query.IsRunning );
|
||||
Assert.IsTrue( Query.TotalResults > 0 );
|
||||
Assert.IsTrue( Query.Items.Length > 0 );
|
||||
|
||||
Console.WriteLine( "Query.TotalResults: {0}", Query.TotalResults );
|
||||
Console.WriteLine( "Query.Items.Length: {0}", Query.Items.Length );
|
||||
|
||||
foreach ( var item in Query.Items )
|
||||
{
|
||||
Console.WriteLine( "{0}", item.Title );
|
||||
Assert.AreEqual<ulong>( item.OwnerId, 76561197960279927 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{3F6183AD-D966-44F2-A6EB-42E61E591B49}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Facepunch.Steamworks.Test</RootNamespace>
|
||||
<AssemblyName>Facepunch.Steamworks.Test</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||
<IsCodedUITest>False</IsCodedUITest>
|
||||
<TestProjectType>UnitTest</TestProjectType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
</ItemGroup>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="Client\Client.cs" />
|
||||
<Compile Include="Client\Workshop.cs" />
|
||||
<Compile Include="Client\Networking.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Client\Friends.cs" />
|
||||
<Compile Include="Server\Inventory.cs" />
|
||||
<Compile Include="Server\Server.cs" />
|
||||
<Compile Include="Server\Stats.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Facepunch.Steamworks\Facepunch.Steamworks.csproj">
|
||||
<Project>{dc2d9fa9-f005-468f-8581-85c79f4e0034}</Project>
|
||||
<Name>Facepunch.Steamworks</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Client\Serverlist.cs" />
|
||||
<Compile Include="Client\Stats.cs" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</When>
|
||||
</Choose>
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
@ -0,0 +1,55 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DefineConstants>TRACE;DEBUG;TEST_WIN32</DefineConstants>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DefineConstants>TRACE;TEST_WIN32</DefineConstants>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Facepunch.Steamworks\Facepunch.Steamworks.Win32.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="steam_api.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.*" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0-beta4" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.0.0-beta4" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="9.0.2-beta1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="ClanTest.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,54 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DefineConstants>TRACE;DEBUG;TEST_WIN64</DefineConstants>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="steam_api64.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.*" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0-beta4" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.0.0-beta4" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="9.0.2-beta1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="ClanTest.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
154
Facepunch.Steamworks.Test/FriendsTest.cs
Normal file
154
Facepunch.Steamworks.Test/FriendsTest.cs
Normal file
@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
[TestClass]
|
||||
public class FriendsTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void GetFriends()
|
||||
{
|
||||
foreach ( var friend in SteamFriends.GetFriends() )
|
||||
{
|
||||
Console.WriteLine( $"{friend.Id.Value}: {friend.Name} (Friend:{friend.IsFriend}) (Blocked:{friend.IsBlocked})" );
|
||||
Console.WriteLine( $" {string.Join( ", ", friend.NameHistory )}" );
|
||||
|
||||
// Assert.IsNotNull( friend.GetAvatar( Steamworks.Friends.AvatarSize.Medium ) );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetBlocked()
|
||||
{
|
||||
foreach ( var friend in SteamFriends.GetBlocked() )
|
||||
{
|
||||
Console.WriteLine( $"{friend.Id.Value}: {friend.Name} (Friend:{friend.IsFriend}) (Blocked:{friend.IsBlocked})" );
|
||||
Console.WriteLine( $" {string.Join( ", ", friend.NameHistory )}" );
|
||||
|
||||
// Assert.IsNotNull( friend.GetAvatar( Steamworks.Friends.AvatarSize.Medium ) );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetPlayedWith()
|
||||
{
|
||||
foreach ( var friend in SteamFriends.GetPlayedWith() )
|
||||
{
|
||||
await friend.RequestInfoAsync();
|
||||
|
||||
Console.WriteLine( $"{friend.Id.Value}: {friend.Name} (Friend:{friend.IsFriend}) (Blocked:{friend.IsBlocked})" );
|
||||
Console.WriteLine( $" {string.Join( ", ", friend.NameHistory )}" );
|
||||
|
||||
// Assert.IsNotNull( friend.GetAvatar( Steamworks.Friends.AvatarSize.Medium ) );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task LargeAvatar()
|
||||
{
|
||||
ulong id = (ulong)(76561197960279927 + (new Random().Next() % 10000));
|
||||
|
||||
var image = await SteamFriends.GetLargeAvatarAsync( id );
|
||||
if ( !image.HasValue )
|
||||
return;
|
||||
|
||||
Console.WriteLine( $"image.Width {image.Value.Width}" );
|
||||
Console.WriteLine( $"image.Height {image.Value.Height}" );
|
||||
|
||||
DrawImage( image.Value );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task MediumAvatar()
|
||||
{
|
||||
ulong id = (ulong)(76561197960279927 + (new Random().Next() % 10000));
|
||||
|
||||
Console.WriteLine( $"Steam: http://steamcommunity.com/profiles/{id}" );
|
||||
|
||||
var image = await SteamFriends.GetMediumAvatarAsync( id );
|
||||
if ( !image.HasValue )
|
||||
return;
|
||||
|
||||
Console.WriteLine( $"image.Width {image.Value.Width}" );
|
||||
Console.WriteLine( $"image.Height {image.Value.Height}" );
|
||||
|
||||
DrawImage( image.Value );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task SmallAvatar()
|
||||
{
|
||||
ulong id = (ulong)(76561197960279927 + (new Random().Next() % 10000));
|
||||
|
||||
var image = await SteamFriends.GetSmallAvatarAsync( id );
|
||||
if ( !image.HasValue )
|
||||
return;
|
||||
|
||||
Console.WriteLine( $"image.Width {image.Value.Width}" );
|
||||
Console.WriteLine( $"image.Height {image.Value.Height}" );
|
||||
|
||||
DrawImage( image.Value );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetFriendsAvatars()
|
||||
{
|
||||
foreach ( var friend in SteamFriends.GetFriends() )
|
||||
{
|
||||
Console.WriteLine( $"{friend.Id.Value}: {friend.Name}" );
|
||||
|
||||
var image = await friend.GetSmallAvatarAsync();
|
||||
if ( image.HasValue )
|
||||
{
|
||||
DrawImage( image.Value );
|
||||
}
|
||||
|
||||
// Assert.IsNotNull( friend.GetAvatar( Steamworks.Friends.AvatarSize.Medium ) );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task OpenWebOverlay()
|
||||
{
|
||||
if ( SteamUtils.IsOverlayEnabled )
|
||||
Console.WriteLine( "Overlay Is Enabled" );
|
||||
else
|
||||
Console.WriteLine( "Overlay Is Not Enabled" );
|
||||
|
||||
SteamFriends.OpenWebOverlay( "https://www.google.com/" );
|
||||
|
||||
await Task.Delay( 2000 );
|
||||
}
|
||||
|
||||
|
||||
public static void DrawImage( Image img )
|
||||
{
|
||||
var grad = " -:+#";
|
||||
|
||||
for ( int y = 0; y < img.Height; y++ )
|
||||
{
|
||||
var str = "";
|
||||
|
||||
for ( int x = 0; x < img.Width; x++ )
|
||||
{
|
||||
var p = img.GetPixel( x, y );
|
||||
|
||||
var brightness = 1 - ((float)(p.r + p.g + p.b) / (255.0f * 3.0f));
|
||||
var c = (int)((grad.Length) * brightness);
|
||||
if ( c > 3 ) c = 3;
|
||||
str += grad[c];
|
||||
|
||||
}
|
||||
|
||||
Console.WriteLine( str );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
32
Facepunch.Steamworks.Test/GameServerStatsTest.cs
Normal file
32
Facepunch.Steamworks.Test/GameServerStatsTest.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public class GameServerStatsTest
|
||||
{
|
||||
static SteamId Garry = 76561197960279927;
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetAchievement()
|
||||
{
|
||||
var result = await SteamServerStats.RequestUserStatsAsync( Garry );
|
||||
Assert.AreEqual( result, Result.OK );
|
||||
|
||||
var value = SteamServerStats.GetAchievement( Garry, "COLLECT_100_WOOD" );
|
||||
Assert.IsTrue( value );
|
||||
|
||||
value = SteamServerStats.GetAchievement( Garry, "ACHIVEMENT_THAT_DOESNT_EXIST" );
|
||||
Assert.IsFalse( value );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
128
Facepunch.Steamworks.Test/GameServerTest.cs
Normal file
128
Facepunch.Steamworks.Test/GameServerTest.cs
Normal file
@ -0,0 +1,128 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
[TestClass]
|
||||
public partial class GameServerTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void Init()
|
||||
{
|
||||
SteamServer.DedicatedServer = true;
|
||||
SteamServer.DedicatedServer = false;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task PublicIp()
|
||||
{
|
||||
while ( true )
|
||||
{
|
||||
var ip = SteamServer.PublicIp;
|
||||
|
||||
if ( ip == null )
|
||||
{
|
||||
await Task.Delay( 10 );
|
||||
continue;
|
||||
}
|
||||
|
||||
Assert.IsNotNull( ip );
|
||||
Console.WriteLine( ip.ToString() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task BeginAuthSession()
|
||||
{
|
||||
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||||
bool finished = false;
|
||||
string failed = null;
|
||||
AuthResponse response = AuthResponse.AuthTicketInvalidAlreadyUsed;
|
||||
|
||||
//
|
||||
// Clientside calls this function, gets ticket
|
||||
//
|
||||
var clientTicket = SteamUser.GetAuthSessionTicket( NetIdentity.LocalHost );
|
||||
|
||||
//
|
||||
// The client sends this data to the server along with their steamid
|
||||
//
|
||||
var ticketData = clientTicket.Data;
|
||||
var clientSteamId = SteamClient.SteamId;
|
||||
|
||||
//
|
||||
// Server listens to auth responses from Gabe
|
||||
//
|
||||
SteamServer.OnValidateAuthTicketResponse += ( steamid, ownerid, rsponse ) =>
|
||||
{
|
||||
finished = true;
|
||||
response = rsponse;
|
||||
|
||||
if ( steamid == 0 )
|
||||
failed = $"steamid is 0! {steamid} != {ownerid} ({rsponse})";
|
||||
|
||||
if ( ownerid == 0 )
|
||||
failed = $"ownerid is 0! {steamid} != {ownerid} ({rsponse})";
|
||||
|
||||
if ( steamid != ownerid )
|
||||
failed = $"Steamid and Ownerid are different! {steamid} != {ownerid} ({rsponse})";
|
||||
};
|
||||
|
||||
//
|
||||
// Server gets the ticket, starts authing
|
||||
//
|
||||
if ( !SteamServer.BeginAuthSession( ticketData, clientSteamId ) )
|
||||
{
|
||||
Assert.Fail( "BeginAuthSession returned false, called bullshit without even having to check with Gabe" );
|
||||
}
|
||||
|
||||
//
|
||||
// Wait for that to go through steam
|
||||
//
|
||||
while ( !finished )
|
||||
{
|
||||
if ( stopwatch.Elapsed.TotalSeconds > 5 )
|
||||
throw new System.Exception( "Took too long waiting for AuthSessionResponse.OK" );
|
||||
|
||||
await Task.Delay( 10 );
|
||||
}
|
||||
|
||||
Assert.AreEqual( response, AuthResponse.OK );
|
||||
|
||||
if ( failed != null )
|
||||
Assert.Fail( failed );
|
||||
|
||||
finished = false;
|
||||
stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
||||
|
||||
//
|
||||
// The client is leaving, and now wants to cancel the ticket
|
||||
//
|
||||
|
||||
Assert.AreNotEqual( 0, clientTicket.Handle );
|
||||
clientTicket.Cancel();
|
||||
|
||||
//
|
||||
// We should get another callback
|
||||
//
|
||||
while ( !finished )
|
||||
{
|
||||
if ( stopwatch.Elapsed.TotalSeconds > 5 )
|
||||
throw new System.Exception( "Took too long waiting for AuthSessionResponse.AuthTicketCanceled" );
|
||||
|
||||
await Task.Delay( 10 );
|
||||
}
|
||||
|
||||
if ( failed != null )
|
||||
Assert.Fail( failed );
|
||||
|
||||
//Assert.AreEqual( response, AuthResponse.AuthTicketCanceled );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
32
Facepunch.Steamworks.Test/InputTest.cs
Normal file
32
Facepunch.Steamworks.Test/InputTest.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
[DeploymentItem( "controller_config/game_actions_252490.vdf" )]
|
||||
public class InputTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void ControllerList()
|
||||
{
|
||||
foreach ( var controller in SteamInput.Controllers )
|
||||
{
|
||||
Console.Write( $"Controller: {controller}" );
|
||||
|
||||
var dstate = controller.GetDigitalState( "fire" );
|
||||
var astate = controller.GetAnalogState( "Move" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
223
Facepunch.Steamworks.Test/InventoryTest.cs
Normal file
223
Facepunch.Steamworks.Test/InventoryTest.cs
Normal file
@ -0,0 +1,223 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public class InventoryTest
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task LoadItemDefinitionsAsync()
|
||||
{
|
||||
var result = await SteamInventory.WaitForDefinitions( 5 );
|
||||
Assert.IsTrue( result );
|
||||
|
||||
result = await SteamInventory.WaitForDefinitions( 5 );
|
||||
Assert.IsTrue( result );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetDefinitions()
|
||||
{
|
||||
await SteamInventory.WaitForDefinitions();
|
||||
|
||||
Assert.IsNotNull( SteamInventory.Definitions );
|
||||
|
||||
foreach ( var def in SteamInventory.Definitions )
|
||||
{
|
||||
Console.WriteLine( $"[{def.Id:0000000000}] {def.Name} [{def.Type}]" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetDefinitionsWithPrices()
|
||||
{
|
||||
var defs = await SteamInventory.GetDefinitionsWithPricesAsync();
|
||||
|
||||
foreach ( var def in defs )
|
||||
{
|
||||
Console.WriteLine( $"[{def.Id:0000000000}] {def.Name} [{def.LocalPriceFormatted}]" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetAllItems()
|
||||
{
|
||||
await SteamInventory.WaitForDefinitions();
|
||||
|
||||
var result = await SteamInventory.GetAllItemsAsync();
|
||||
|
||||
Assert.IsTrue( result.HasValue );
|
||||
Assert.IsTrue( result.Value.ItemCount > 0 );
|
||||
|
||||
using ( result )
|
||||
{
|
||||
var items = result.Value.GetItems( true );
|
||||
|
||||
Assert.IsNotNull( items );
|
||||
|
||||
foreach ( var item in items )
|
||||
{
|
||||
Console.WriteLine( $"{item.Id} / {item.DefId} / {item.Quantity} / {item.Def?.Name} /[{item.IsNoTrade}|{item.IsRemoved}|{item.IsConsumed}] " );
|
||||
|
||||
foreach ( var prop in item.Properties )
|
||||
{
|
||||
Console.WriteLine( $" {prop.Key} : {prop.Value}" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetItemSpecialProperties()
|
||||
{
|
||||
await SteamInventory.WaitForDefinitions();
|
||||
|
||||
var result = await SteamInventory.GetAllItemsAsync();
|
||||
|
||||
Assert.IsTrue( result.HasValue );
|
||||
Assert.IsTrue( result.Value.ItemCount > 0 );
|
||||
|
||||
using ( result )
|
||||
{
|
||||
var items = result.Value.GetItems( true );
|
||||
|
||||
Assert.IsNotNull( items );
|
||||
|
||||
foreach ( var item in items )
|
||||
{
|
||||
Console.WriteLine( $"{item.Id} / {item.DefId} / {item.Quantity} / {item.Def?.Name} " );
|
||||
|
||||
Console.WriteLine( $" Acquired: {item.Acquired}" );
|
||||
Console.WriteLine( $" Origin: {item.Origin}" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetAllItemsMultipleTimes()
|
||||
{
|
||||
await SteamInventory.WaitForDefinitions();
|
||||
|
||||
var fresult = await SteamInventory.GetAllItemsAsync();
|
||||
|
||||
Assert.IsTrue( fresult.HasValue );
|
||||
Assert.IsTrue( fresult.Value.ItemCount > 0 );
|
||||
|
||||
await Task.Delay( 1000 );
|
||||
|
||||
var result = await SteamInventory.GetAllItemsAsync();
|
||||
|
||||
Assert.IsTrue( result.HasValue );
|
||||
Assert.IsTrue( result.Value.GetItems().Length == fresult.Value.ItemCount );
|
||||
|
||||
|
||||
await Task.Delay( 1000 );
|
||||
|
||||
result = await SteamInventory.GetAllItemsAsync();
|
||||
|
||||
Assert.IsTrue( result.HasValue );
|
||||
Assert.IsTrue( result.Value.ItemCount == fresult.Value.ItemCount );
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Items()
|
||||
{
|
||||
SteamInventory.GetAllItems();
|
||||
await SteamInventory.WaitForDefinitions();
|
||||
|
||||
while ( SteamInventory.Items == null )
|
||||
{
|
||||
await Task.Delay( 10 );
|
||||
}
|
||||
|
||||
Assert.IsNotNull( SteamInventory.Items );
|
||||
|
||||
foreach ( var item in SteamInventory.Items )
|
||||
{
|
||||
Console.WriteLine( $"{item.Id} / {item.DefId} / {item.Quantity} / {item.Def.Name}" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetExchanges()
|
||||
{
|
||||
var result = await SteamInventory.WaitForDefinitions( 5 );
|
||||
Assert.IsTrue( result );
|
||||
|
||||
foreach ( var def in SteamInventory.Definitions )
|
||||
{
|
||||
var exchangelist = def.GetRecipes();
|
||||
if ( exchangelist == null ) continue;
|
||||
|
||||
foreach ( var exchange in exchangelist )
|
||||
{
|
||||
Assert.AreEqual( exchange.Result, def );
|
||||
|
||||
Console.WriteLine( $"{def.Name}:" );
|
||||
|
||||
foreach ( var item in exchange.Ingredients )
|
||||
{
|
||||
Console.WriteLine( $" {item.Count} x {item.Definition?.Name ?? item.DefinitionId.ToString()}" );
|
||||
}
|
||||
|
||||
Console.WriteLine( $"" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Serialize()
|
||||
{
|
||||
await SteamInventory.WaitForDefinitions();
|
||||
|
||||
var result = await SteamInventory.GetAllItemsAsync();
|
||||
|
||||
Assert.IsTrue( result.HasValue );
|
||||
|
||||
var data = result.Value.Serialize();
|
||||
|
||||
Assert.IsNotNull( data );
|
||||
|
||||
Console.WriteLine( string.Join( "", data.Select( x => x.ToString( "x" ) ) ) );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Deserialize()
|
||||
{
|
||||
await SteamInventory.WaitForDefinitions();
|
||||
|
||||
byte[] data;
|
||||
int itemCount;
|
||||
|
||||
// Serialize
|
||||
{
|
||||
var result = await SteamInventory.GetAllItemsAsync();
|
||||
Assert.IsTrue( result.HasValue );
|
||||
itemCount = result.Value.ItemCount;
|
||||
data = result.Value.Serialize();
|
||||
Assert.IsNotNull( data );
|
||||
result.Value.Dispose();
|
||||
}
|
||||
|
||||
await Task.Delay( 2000 );
|
||||
|
||||
// Deserialize
|
||||
{
|
||||
var result = await SteamInventory.DeserializeAsync( data );
|
||||
Assert.IsTrue( result.HasValue );
|
||||
Assert.AreEqual( itemCount, result.Value.ItemCount );
|
||||
result.Value.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
163
Facepunch.Steamworks.Test/NetworkingSockets.cs
Normal file
163
Facepunch.Steamworks.Test/NetworkingSockets.cs
Normal file
@ -0,0 +1,163 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public partial class NetworkingSocketsTest
|
||||
{
|
||||
void DebugOutput( NetDebugOutput type, string text )
|
||||
{
|
||||
Console.WriteLine( $"[NET:{type}]\t\t{text}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CreateRelayServer()
|
||||
{
|
||||
SteamNetworkingUtils.DebugLevel = NetDebugOutput.Everything;
|
||||
SteamNetworkingUtils.OnDebugOutput += DebugOutput;
|
||||
|
||||
var si = SteamNetworkingSockets.CreateRelaySocket<TestSocketInterface>();
|
||||
|
||||
Console.WriteLine( $"Created Socket: {si}" );
|
||||
|
||||
// Give it a second for something to happen
|
||||
await Task.Delay( 1000 );
|
||||
|
||||
si.Close();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CreateNormalServer()
|
||||
{
|
||||
SteamNetworkingUtils.DebugLevel = NetDebugOutput.Everything;
|
||||
SteamNetworkingUtils.OnDebugOutput += DebugOutput;
|
||||
|
||||
var si = SteamNetworkingSockets.CreateNormalSocket<TestSocketInterface>( Data.NetAddress.AnyIp( 21893 ) );
|
||||
|
||||
Console.WriteLine( $"Created Socket: {si}" );
|
||||
|
||||
// Give it a second for something to happen
|
||||
await Task.Delay( 1000 );
|
||||
|
||||
si.Close();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CreateRelayServerFakeIP()
|
||||
{
|
||||
SteamNetworkingUtils.DebugLevel = NetDebugOutput.Everything;
|
||||
SteamNetworkingUtils.OnDebugOutput += DebugOutput;
|
||||
|
||||
var si = SteamNetworkingSockets.CreateRelaySocketFakeIP<TestSocketInterface>();
|
||||
|
||||
Console.WriteLine( $"Created Socket: {si}" );
|
||||
|
||||
// Give it a second for something to happen
|
||||
await Task.Delay( 1000 );
|
||||
|
||||
si.Close();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task RelayEndtoEnd()
|
||||
{
|
||||
SteamNetworkingUtils.InitRelayNetworkAccess();
|
||||
SteamNetworkingUtils.DebugLevel = NetDebugOutput.Warning;
|
||||
SteamNetworkingUtils.OnDebugOutput += DebugOutput;
|
||||
|
||||
// For some reason giving steam a couple of seconds here
|
||||
// seems to prevent it returning null connections from ConnectNormal
|
||||
await Task.Delay( 2000 );
|
||||
|
||||
Console.WriteLine( $"----- Creating Socket Relay Socket.." );
|
||||
var socket = SteamNetworkingSockets.CreateRelaySocket<TestSocketInterface>( 6 );
|
||||
var server = socket.RunAsync();
|
||||
|
||||
await Task.Delay( 1000 );
|
||||
|
||||
Console.WriteLine( $"----- Connecting To Socket via SteamId ({SteamClient.SteamId})" );
|
||||
var connection = SteamNetworkingSockets.ConnectRelay<TestConnectionInterface>( SteamClient.SteamId, 6 );
|
||||
var client = connection.RunAsync();
|
||||
|
||||
await Task.WhenAll( server, client );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task NormalEndtoEnd()
|
||||
{
|
||||
SteamNetworkingUtils.DebugLevel = NetDebugOutput.Everything;
|
||||
SteamNetworkingUtils.OnDebugOutput += DebugOutput;
|
||||
|
||||
// For some reason giving steam a couple of seconds here
|
||||
// seems to prevent it returning null connections from ConnectNormal
|
||||
await Task.Delay( 2000 );
|
||||
|
||||
//
|
||||
// Start the server
|
||||
//
|
||||
Console.WriteLine( "CreateNormalSocket" );
|
||||
var socket = SteamNetworkingSockets.CreateNormalSocket<TestSocketInterface>( NetAddress.AnyIp( 12445 ) );
|
||||
var server = socket.RunAsync();
|
||||
|
||||
//
|
||||
// Start the client
|
||||
//
|
||||
Console.WriteLine( "ConnectNormal" );
|
||||
var connection = SteamNetworkingSockets.ConnectNormal<TestConnectionInterface>( NetAddress.From( "127.0.0.1", 12445 ) );
|
||||
var client = connection.RunAsync();
|
||||
|
||||
await Task.WhenAll( server, client );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task RelayEndtoEndFakeIP()
|
||||
{
|
||||
SteamNetworkingUtils.InitRelayNetworkAccess();
|
||||
SteamNetworkingUtils.DebugLevel = NetDebugOutput.Warning;
|
||||
SteamNetworkingUtils.OnDebugOutput += DebugOutput;
|
||||
|
||||
// For some reason giving steam a couple of seconds here
|
||||
// seems to prevent it returning null connections from ConnectNormal
|
||||
await Task.Delay( 2000 );
|
||||
|
||||
Console.WriteLine( $"----- Creating Socket Relay Socket.." );
|
||||
var socket = SteamNetworkingSockets.CreateRelaySocketFakeIP<TestSocketInterface>();
|
||||
var server = socket.RunAsync();
|
||||
|
||||
await Task.Delay( 1000 );
|
||||
|
||||
Console.WriteLine( $"----- Retrieving Fake IP.." );
|
||||
SteamNetworkingSockets.GetFakeIP( 0, out NetAddress address );
|
||||
|
||||
Console.WriteLine( $"----- Connecting To Socket via Fake IP ({address})" );
|
||||
var connection = SteamNetworkingSockets.ConnectNormal<TestConnectionInterface>( address );
|
||||
var client = connection.RunAsync();
|
||||
|
||||
await Task.WhenAll( server, client );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NetAddressTest()
|
||||
{
|
||||
{
|
||||
var n = NetAddress.From( "127.0.0.1", 12445 );
|
||||
Assert.AreEqual( n.ToString(), "127.0.0.1:12445" );
|
||||
}
|
||||
|
||||
{
|
||||
var n = NetAddress.AnyIp( 5543 );
|
||||
Assert.AreEqual( n.ToString(), "[::]:5543" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
public partial class NetworkingSocketsTest
|
||||
{
|
||||
private class TestConnectionInterface : ConnectionManager
|
||||
{
|
||||
public override void OnConnectionChanged( ConnectionInfo data )
|
||||
{
|
||||
Console.WriteLine( $"[Connection][{Connection}] [{data.State}]" );
|
||||
|
||||
base.OnConnectionChanged( data );
|
||||
}
|
||||
|
||||
public override void OnConnecting( ConnectionInfo data )
|
||||
{
|
||||
Console.WriteLine( $" - OnConnecting" );
|
||||
base.OnConnecting( data );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Client is connected. They move from connecting to Connections
|
||||
/// </summary>
|
||||
public override void OnConnected( ConnectionInfo data )
|
||||
{
|
||||
Console.WriteLine( $" - OnConnected" );
|
||||
base.OnConnected( data );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The connection has been closed remotely or disconnected locally. Check data.State for details.
|
||||
/// </summary>
|
||||
public override void OnDisconnected( ConnectionInfo data )
|
||||
{
|
||||
Console.WriteLine( $" - OnDisconnected" );
|
||||
base.OnDisconnected( data );
|
||||
}
|
||||
|
||||
internal async Task RunAsync()
|
||||
{
|
||||
Console.WriteLine( "[Connection] RunAsync" );
|
||||
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
|
||||
Console.WriteLine( "[Connection] Connecting" );
|
||||
while ( Connecting )
|
||||
{
|
||||
await Task.Delay( 10 );
|
||||
|
||||
if ( sw.Elapsed.TotalSeconds > 10 )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !Connected )
|
||||
{
|
||||
Console.WriteLine( "[Connection] Couldn't connect!" );
|
||||
Console.WriteLine( Connection.DetailedStatus() );
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine( "[Connection] Hey We're Connected!" );
|
||||
|
||||
|
||||
sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
while ( Connected )
|
||||
{
|
||||
Receive();
|
||||
await Task.Delay( 100 );
|
||||
|
||||
if ( sw.Elapsed.TotalSeconds > 30 )
|
||||
{
|
||||
Assert.Fail( "Client Took Too Long" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override unsafe void OnMessage( IntPtr data, int size, long messageNum, long recvTime, int channel )
|
||||
{
|
||||
// We're only sending strings, so it's fine to read this like this
|
||||
var str = Utility.Utf8NoBom.GetString( (byte*) data, size );
|
||||
|
||||
Console.WriteLine( $"[Connection][{messageNum}][{recvTime}][{channel}] \"{str}\"" );
|
||||
|
||||
if ( str.Contains( "Hello" ) )
|
||||
{
|
||||
Console.WriteLine( $"[Connection][{messageNum}][{recvTime}][{channel}] Sending: Hello, How are you!?" );
|
||||
Connection.SendMessage( "Hello, How are you!?" );
|
||||
|
||||
Console.WriteLine( $"[Connection][{messageNum}][{recvTime}][{channel}] Sending: How do you like 20 messages in a row?" );
|
||||
Connection.SendMessage( "How do you like 20 messages in a row?" );
|
||||
|
||||
var connections = new[] { Connection };
|
||||
var results = new Result[1];
|
||||
for ( int i=0; i<20; i++ )
|
||||
{
|
||||
Console.WriteLine( $"[Connection][{messageNum}][{recvTime}][{channel}] Sending: BLAMMO {i}!" );
|
||||
SendMessages( connections, connections.Length, $"BLAMMO {i}!", results: results );
|
||||
Assert.AreEqual( Result.OK, results[0] );
|
||||
}
|
||||
|
||||
Connection.Flush();
|
||||
}
|
||||
|
||||
if ( str.Contains( "status" ))
|
||||
{
|
||||
Console.WriteLine( Connection.DetailedStatus() );
|
||||
}
|
||||
|
||||
if ( str.Contains( "how about yourself" ) )
|
||||
{
|
||||
Connection.SendMessage( "I'm great, but I have to go now, bye." );
|
||||
}
|
||||
|
||||
if ( str.Contains( "hater" ) )
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
public partial class NetworkingSocketsTest
|
||||
{
|
||||
private class TestSocketInterface : SocketManager
|
||||
{
|
||||
public bool HasFinished = false;
|
||||
|
||||
public override void OnConnectionChanged( Connection connection, ConnectionInfo data )
|
||||
{
|
||||
Console.WriteLine( $"[Socket{Socket}][connection:{connection}][data.Identity:{data.Identity}] [data.State:{data.State}]" );
|
||||
|
||||
base.OnConnectionChanged( connection, data );
|
||||
}
|
||||
|
||||
public override void OnConnecting( Connection connection, ConnectionInfo data )
|
||||
{
|
||||
Console.WriteLine( $" - OnConnecting" );
|
||||
base.OnConnecting( connection, data );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Client is connected. They move from connecting to Connections
|
||||
/// </summary>
|
||||
public override void OnConnected( Connection connection, ConnectionInfo data )
|
||||
{
|
||||
Console.WriteLine( $"" );
|
||||
Console.WriteLine( $"Socket -> OnConnected:" );
|
||||
Console.WriteLine( $" data.Address: {data.Address}" );
|
||||
Console.WriteLine( $" data.Identity: {data.Identity}" );
|
||||
Console.WriteLine( $" data.Identity.Steamid: {data.Identity.SteamId}" );
|
||||
Console.WriteLine( $" data.Identity.IsIpAddress: {data.Identity.IsIpAddress}" );
|
||||
Console.WriteLine( $" data.Identity.IsLocalHost: {data.Identity.IsLocalHost}" );
|
||||
Console.WriteLine( $" data.Identity.IsSteamId: {data.Identity.IsSteamId}" );
|
||||
Console.WriteLine( $" data.Identity.Address: {data.Identity.Address}" );
|
||||
Console.WriteLine( $" data.Identity.Address.Address: {data.Identity.Address.Address}" );
|
||||
Console.WriteLine( $" data.Identity.Address.Port: {data.Identity.Address.Port}" );
|
||||
Console.WriteLine( $"" );
|
||||
|
||||
base.OnConnected( connection, data );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The connection has been closed remotely or disconnected locally. Check data.State for details.
|
||||
/// </summary>
|
||||
public override void OnDisconnected( Connection connection, ConnectionInfo data )
|
||||
{
|
||||
Console.WriteLine( $" - OnDisconnected" );
|
||||
|
||||
base.OnDisconnected( connection, data );
|
||||
}
|
||||
|
||||
internal async Task RunAsync()
|
||||
{
|
||||
var sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
|
||||
while ( Connected.Count == 0 )
|
||||
{
|
||||
await Task.Delay( 10 );
|
||||
|
||||
if ( sw.Elapsed.TotalSeconds > 10 )
|
||||
{
|
||||
Assert.Fail( "Client Took Too Long To Connect" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
await Task.Delay( 1000 );
|
||||
|
||||
var singleClient = Connected.First();
|
||||
|
||||
singleClient.SendMessage( "Hey?" );
|
||||
await Task.Delay( 100 );
|
||||
singleClient.SendMessage( "Anyone?" );
|
||||
await Task.Delay( 100 );
|
||||
singleClient.SendMessage( "What's this?" );
|
||||
await Task.Delay( 100 );
|
||||
singleClient.SendMessage( "What's your status?" );
|
||||
await Task.Delay( 10 );
|
||||
singleClient.SendMessage( "Greetings!!??" );
|
||||
await Task.Delay( 100 );
|
||||
singleClient.SendMessage( "Hello Client!?" );
|
||||
|
||||
sw = System.Diagnostics.Stopwatch.StartNew();
|
||||
|
||||
Console.WriteLine( $"Socket: Listening" );
|
||||
|
||||
while ( Connected.Contains( singleClient ) )
|
||||
{
|
||||
Receive();
|
||||
await Task.Delay( 100 );
|
||||
|
||||
if ( sw.Elapsed.TotalSeconds > 30 )
|
||||
{
|
||||
Console.WriteLine( "Socket: This all took too long - throwing an exception" );
|
||||
Assert.Fail( "Socket Took Too Long" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine( $"Socket: Closing connection because {Connected.Count()} Connected" );
|
||||
|
||||
await Task.Delay( 1000 );
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
public override unsafe void OnMessage( Connection connection, NetIdentity identity, IntPtr data, int size, long messageNum, long recvTime, int channel )
|
||||
{
|
||||
// We're only sending strings, so it's fine to read this like this
|
||||
var str = Utility.Utf8NoBom.GetString( (byte*)data, size );
|
||||
|
||||
Console.WriteLine( $"[SOCKET][{connection}[{identity}][{messageNum}][{recvTime}][{channel}] \"{str}\"" );
|
||||
|
||||
if ( str.Contains( "Hello, How are you" ) )
|
||||
{
|
||||
connection.SendMessage( "I'm great thanks, how about yourself?" );
|
||||
}
|
||||
|
||||
if ( str.Contains( "bye" ) )
|
||||
{
|
||||
connection.SendMessage( "See you later, hater." );
|
||||
connection.Flush();
|
||||
connection.Close( true, 10, "Said Bye" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
63
Facepunch.Steamworks.Test/NetworkingUtils.cs
Normal file
63
Facepunch.Steamworks.Test/NetworkingUtils.cs
Normal file
@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public class NetworkUtilsTest
|
||||
{
|
||||
static string GarrysLocation = "lhr=4+0,ams=13+1/10+0,par=17+1/12+0,lux=17+1,fra=18+1/18+0,sto=25+2,sto2=26+2,mad=27+2,vie=31+3/30+0,iad=90+9/75+0,sgp=173+17/174+17,gru=200+20/219+0";
|
||||
|
||||
[TestMethod]
|
||||
public async Task LocalPingLocation()
|
||||
{
|
||||
await SteamNetworkingUtils.WaitForPingDataAsync();
|
||||
|
||||
for ( int i = 0; i < 10; i++ )
|
||||
{
|
||||
var pl = SteamNetworkingUtils.LocalPingLocation;
|
||||
if ( !pl.HasValue )
|
||||
{
|
||||
await Task.Delay( 1000 );
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine( $"{i} Seconds Until Result: {pl}" );
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void PingLocationParse()
|
||||
{
|
||||
var pl = Data.NetPingLocation.TryParseFromString( GarrysLocation );
|
||||
|
||||
Assert.IsTrue( pl.HasValue );
|
||||
|
||||
Console.WriteLine( $"Parsed OKAY! {pl}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetEstimatedPing()
|
||||
{
|
||||
await SteamNetworkingUtils.WaitForPingDataAsync();
|
||||
|
||||
var garrysping = Data.NetPingLocation.TryParseFromString( GarrysLocation );
|
||||
Assert.IsTrue( garrysping.HasValue );
|
||||
|
||||
var ping = SteamNetworkingUtils.EstimatePingTo( garrysping.Value );
|
||||
Assert.IsTrue( ping > 0 );
|
||||
|
||||
Console.WriteLine( $"Ping returned: {ping}" );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
30
Facepunch.Steamworks.Test/RemotePlayTest.cs
Normal file
30
Facepunch.Steamworks.Test/RemotePlayTest.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public class RemotePlayTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void BasicUsability()
|
||||
{
|
||||
Console.WriteLine( $"Sessions: {SteamRemotePlay.SessionCount}" );
|
||||
|
||||
var session = SteamRemotePlay.GetSession( 4 );
|
||||
|
||||
Assert.IsFalse( session.IsValid );
|
||||
Assert.IsFalse( session.SteamId.IsValid );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
79
Facepunch.Steamworks.Test/RemoteStorageTest.cs
Normal file
79
Facepunch.Steamworks.Test/RemoteStorageTest.cs
Normal file
@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public class RemoteStorageTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void Quotas()
|
||||
{
|
||||
Console.WriteLine( $"SteamRemoteStorage.QuotaBytes: {SteamRemoteStorage.QuotaBytes}" );
|
||||
Console.WriteLine( $"SteamRemoteStorage.QuotaRemainingBytes: {SteamRemoteStorage.QuotaRemainingBytes}" );
|
||||
Console.WriteLine( $"SteamRemoteStorage.QuotaUsedBytes: {SteamRemoteStorage.QuotaUsedBytes}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsCloudEnabled()
|
||||
{
|
||||
Console.WriteLine( $"SteamRemoteStorage.IsCloudEnabled: {SteamRemoteStorage.IsCloudEnabled}" );
|
||||
Console.WriteLine( $"SteamRemoteStorage.IsCloudEnabledForAccount: {SteamRemoteStorage.IsCloudEnabledForAccount}" );
|
||||
Console.WriteLine( $"SteamRemoteStorage.IsCloudEnabledForApp: {SteamRemoteStorage.IsCloudEnabledForApp}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void FileWrite()
|
||||
{
|
||||
var rand = new Random();
|
||||
var testFile = new byte[1024 * 1024 * 100];
|
||||
|
||||
for( int i=0; i< testFile.Length; i++ )
|
||||
{
|
||||
testFile[i] = (byte) i;
|
||||
}
|
||||
|
||||
var written = SteamRemoteStorage.FileWrite( "testfile", testFile );
|
||||
|
||||
Assert.IsTrue( written );
|
||||
Assert.IsTrue( SteamRemoteStorage.FileExists( "testfile" ) );
|
||||
Assert.AreEqual( SteamRemoteStorage.FileSize( "testfile" ), testFile.Length );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void FileRead()
|
||||
{
|
||||
FileWrite();
|
||||
|
||||
var data = SteamRemoteStorage.FileRead( "testfile" );
|
||||
|
||||
Assert.IsNotNull( data );
|
||||
|
||||
for ( int i = 0; i < data.Length; i++ )
|
||||
{
|
||||
Assert.AreEqual( data[i], (byte)i );
|
||||
}
|
||||
|
||||
Assert.AreEqual( SteamRemoteStorage.FileSize( "testfile" ), data.Length );
|
||||
Assert.AreEqual( SteamRemoteStorage.FileSize( "testfile" ), 1024 * 1024 * 100 );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Files()
|
||||
{
|
||||
foreach ( var file in SteamRemoteStorage.Files )
|
||||
{
|
||||
Console.WriteLine( $"{file} ({SteamRemoteStorage.FileSize(file)} {SteamRemoteStorage.FileTime( file )})" );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Linq;
|
||||
|
||||
namespace Facepunch.Steamworks.Test
|
||||
{
|
||||
public partial class Server
|
||||
{
|
||||
[TestMethod]
|
||||
public void InventoryDeserialize()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
|
||||
Assert.IsNull( client.Inventory.SerializedItems );
|
||||
|
||||
client.Inventory.Refresh();
|
||||
|
||||
//
|
||||
// Block until we have the items
|
||||
//
|
||||
while ( client.Inventory.SerializedItems == null )
|
||||
{
|
||||
client.Update();
|
||||
}
|
||||
|
||||
Assert.IsNotNull( client.Inventory.SerializedItems );
|
||||
Assert.IsTrue( client.Inventory.SerializedItems.Length > 4 );
|
||||
|
||||
using ( var server = new Facepunch.Steamworks.Server( 252490, 0, 30002, true, "VersionString" ) )
|
||||
{
|
||||
server.LogOnAnonymous();
|
||||
Assert.IsTrue( server.IsValid );
|
||||
|
||||
var result = server.Inventory.Deserialize( client.Inventory.SerializedItems );
|
||||
|
||||
Assert.IsTrue( result.Block() );
|
||||
Assert.IsNotNull( result.Items );
|
||||
|
||||
foreach ( var item in result.Items )
|
||||
{
|
||||
Console.WriteLine( "Item: {0} ({1})", item.Id, item.DefinitionId );
|
||||
Console.WriteLine( "Item: {0} ({1})", item.Id, item.DefinitionId );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Facepunch.Steamworks.Test
|
||||
{
|
||||
[DeploymentItem( Config.LibraryName + ".dll" )]
|
||||
[DeploymentItem( "steam_appid.txt" )]
|
||||
[DeploymentItem( "tier0_s.dll" )]
|
||||
[DeploymentItem( "vstdlib_s.dll" )]
|
||||
[DeploymentItem( "steamclient.dll" )]
|
||||
[TestClass]
|
||||
public partial class Server
|
||||
{
|
||||
[TestMethod]
|
||||
public void Init()
|
||||
{
|
||||
using ( var server = new Facepunch.Steamworks.Server( 252490, 30001, 30002, 30003, false, "VersionString" ) )
|
||||
{
|
||||
Assert.IsTrue( server.IsValid );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AuthCallback()
|
||||
{
|
||||
using ( var client = new Facepunch.Steamworks.Client( 252490 ) )
|
||||
{
|
||||
Assert.IsTrue( client.IsValid );
|
||||
var ticket = client.Auth.GetAuthSessionTicket();
|
||||
var ticketBinary = ticket.Data;
|
||||
|
||||
using ( var server = new Facepunch.Steamworks.Server( 252490, 30001, 30002, 30003, true, "VersionString" ) )
|
||||
{
|
||||
server.LogOnAnonymous();
|
||||
|
||||
Assert.IsTrue( server.IsValid );
|
||||
|
||||
var auth = server.Auth;
|
||||
|
||||
var Authed = false;
|
||||
|
||||
server.Auth.OnAuthChange = ( steamid, ownerid, status ) =>
|
||||
{
|
||||
Authed = status == ServerAuth.Status.OK;
|
||||
|
||||
Assert.AreEqual( steamid, client.SteamId );
|
||||
Assert.AreEqual( steamid, ownerid );
|
||||
|
||||
Console.WriteLine( "steamid: {0}", steamid );
|
||||
Console.WriteLine( "ownerid: {0}", ownerid );
|
||||
Console.WriteLine( "status: {0}", status );
|
||||
};
|
||||
|
||||
for ( int i = 0; i < 16; i++ )
|
||||
{
|
||||
System.Threading.Thread.Sleep( 10 );
|
||||
GC.Collect();
|
||||
server.Update();
|
||||
GC.Collect();
|
||||
client.Update();
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
if ( !server.Auth.StartSession( ticketBinary, client.SteamId ) )
|
||||
{
|
||||
Assert.Fail( "Start Session returned false" );
|
||||
}
|
||||
GC.Collect();
|
||||
|
||||
//
|
||||
// Server should receive a ServerAuth.Status.OK
|
||||
// message via the OnAuthChange callback
|
||||
//
|
||||
|
||||
for ( int i = 0; i< 100; i++ )
|
||||
{
|
||||
GC.Collect();
|
||||
System.Threading.Thread.Sleep( 100 );
|
||||
GC.Collect();
|
||||
server.Update();
|
||||
client.Update();
|
||||
|
||||
if ( Authed )
|
||||
break;
|
||||
}
|
||||
|
||||
Assert.IsTrue( Authed );
|
||||
|
||||
//
|
||||
// Client cancels ticket
|
||||
//
|
||||
ticket.Cancel();
|
||||
|
||||
//
|
||||
// Server should receive a ticket cancelled message
|
||||
//
|
||||
|
||||
for ( int i = 0; i < 100; i++ )
|
||||
{
|
||||
System.Threading.Thread.Sleep( 100 );
|
||||
server.Update();
|
||||
client.Update();
|
||||
|
||||
if ( !Authed )
|
||||
break;
|
||||
}
|
||||
|
||||
Assert.IsTrue( !Authed );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Facepunch.Steamworks.Test
|
||||
{
|
||||
public partial class Server
|
||||
{
|
||||
[TestMethod]
|
||||
public void StatsGet()
|
||||
{
|
||||
using ( var server = new Facepunch.Steamworks.Server( 252490, 0, 30002, true, "VersionString" ) )
|
||||
{
|
||||
Assert.IsTrue( server.IsValid );
|
||||
server.LogOnAnonymous();
|
||||
|
||||
ulong MySteamId = 76561197960279927;
|
||||
|
||||
server.Stats.Refresh( MySteamId );
|
||||
|
||||
// TODO - Callback on complete
|
||||
|
||||
Thread.Sleep( 2000 );
|
||||
|
||||
var deaths = server.Stats.GetInt( MySteamId, "deaths", -1 );
|
||||
|
||||
Console.WriteLine( "Deaths: {0}", deaths );
|
||||
Assert.IsTrue( deaths > 0 );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
251
Facepunch.Steamworks.Test/ServerlistTest.cs
Normal file
251
Facepunch.Steamworks.Test/ServerlistTest.cs
Normal file
@ -0,0 +1,251 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public partial class ServerListTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void IpAddressConversions()
|
||||
{
|
||||
var ipstr = "185.38.150.40";
|
||||
var ip = IPAddress.Parse( ipstr );
|
||||
|
||||
var ip_int = Utility.IpToInt32( ip );
|
||||
|
||||
var ip_back = Utility.Int32ToIp( ip_int );
|
||||
|
||||
Console.WriteLine( "ipstr: " + ipstr );
|
||||
Console.WriteLine( "ip: " + ip );
|
||||
Console.WriteLine( "ip int: " + ip_int );
|
||||
Console.WriteLine( "ip_back: " + ip_back );
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public async Task ServerListInternetInterupted()
|
||||
{
|
||||
using ( var list = new ServerList.Internet() )
|
||||
{
|
||||
var task = list.RunQueryAsync();
|
||||
|
||||
await Task.Delay( 1000 );
|
||||
|
||||
Console.WriteLine( $"Querying.." );
|
||||
|
||||
list.Cancel();
|
||||
|
||||
foreach ( var s in list.Responsive )
|
||||
{
|
||||
Console.WriteLine( $"{s.Address} {s.Name}" );
|
||||
}
|
||||
|
||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||
Console.WriteLine( $"task.IsCompleted {task.IsCompleted}" );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ServerListInternet()
|
||||
{
|
||||
using ( var list = new ServerList.Internet() )
|
||||
{
|
||||
var success = await list.RunQueryAsync();
|
||||
|
||||
Console.WriteLine( $"success {success}" );
|
||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||
}
|
||||
}
|
||||
|
||||
// Used to reproduce steam serverlist stopping querying after ~10s around august 2023
|
||||
[TestMethod]
|
||||
public async Task RustServerListTest()
|
||||
{
|
||||
using ( var list = new ServerList.Internet() )
|
||||
{
|
||||
list.AddFilter( "secure", "1" );
|
||||
list.AddFilter( "and", "1" );
|
||||
list.AddFilter( "gametype", "v2405" );
|
||||
list.AddFilter( "appid", "252490" );
|
||||
list.AddFilter( "gamedir", "rust" );
|
||||
list.AddFilter( "empty", "1" );
|
||||
|
||||
var success = await list.RunQueryAsync( 90 );
|
||||
|
||||
Console.WriteLine( $"success {success}" );
|
||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task SourceQuery()
|
||||
{
|
||||
using ( var list = new ServerList.Internet() )
|
||||
{
|
||||
var task = list.RunQueryAsync();
|
||||
await Task.Delay( 1000 );
|
||||
list.Cancel();
|
||||
|
||||
foreach ( var s in list.Responsive.Take( 10 ).ToArray() )
|
||||
{
|
||||
Console.WriteLine( $"{s.Name} [{s.Address}]" );
|
||||
|
||||
var rules = await s.QueryRulesAsync();
|
||||
Assert.IsNotNull( rules );
|
||||
|
||||
foreach ( var rule in rules )
|
||||
{
|
||||
Console.WriteLine( $" {rule.Key} = {rule.Value}" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ServerListLan()
|
||||
{
|
||||
using ( var list = new ServerList.LocalNetwork() )
|
||||
{
|
||||
var success = await list.RunQueryAsync();
|
||||
|
||||
Console.WriteLine( $"success {success}" );
|
||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ServerListFavourites()
|
||||
{
|
||||
using ( var list = new ServerList.Favourites() )
|
||||
{
|
||||
var success = await list.RunQueryAsync();
|
||||
|
||||
Console.WriteLine( $"success {success}" );
|
||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ServerListFriends()
|
||||
{
|
||||
using ( var list = new ServerList.Friends() )
|
||||
{
|
||||
var success = await list.RunQueryAsync();
|
||||
|
||||
Console.WriteLine( $"success {success}" );
|
||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ServerListHistory()
|
||||
{
|
||||
using ( var list = new ServerList.History() )
|
||||
{
|
||||
var success = await list.RunQueryAsync();
|
||||
|
||||
Console.WriteLine( $"success {success}" );
|
||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task FilterByMap()
|
||||
{
|
||||
using ( var list = new ServerList.Internet() )
|
||||
{
|
||||
list.AddFilter( "map", "de_dust" );
|
||||
|
||||
var success = await list.RunQueryAsync();
|
||||
|
||||
Console.WriteLine( $"success {success}" );
|
||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||
|
||||
foreach ( var server in list.Responsive )
|
||||
{
|
||||
Assert.AreEqual( server.Map.ToLower(), "de_dust" );
|
||||
|
||||
Console.WriteLine( $"[{server.Map}] - {server.Name}" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ServerListIps()
|
||||
{
|
||||
var ips = new string[]
|
||||
{
|
||||
"31.186.251.76",
|
||||
"31.186.251.76",
|
||||
"31.186.251.76",
|
||||
"31.186.251.76",
|
||||
"31.186.251.76",
|
||||
"74.91.119.142",
|
||||
"74.91.119.142",
|
||||
"74.91.119.142",
|
||||
"74.91.119.142",
|
||||
"74.91.119.142",
|
||||
"74.91.119.142",
|
||||
"74.91.119.142",
|
||||
"74.91.119.142",
|
||||
"74.91.119.142",
|
||||
"74.91.119.142",
|
||||
"74.91.119.142",
|
||||
"74.91.119.142",
|
||||
"139.99.144.70",
|
||||
"139.99.144.70",
|
||||
"139.99.144.70",
|
||||
"139.99.144.70",
|
||||
"139.99.144.70",
|
||||
"74.91.119.142",
|
||||
"74.91.119.142",
|
||||
"74.91.119.142",
|
||||
"74.91.119.142",
|
||||
"95.172.92.176",
|
||||
"95.172.92.176",
|
||||
"95.172.92.176",
|
||||
"95.172.92.176",
|
||||
"95.172.92.176",
|
||||
"164.132.205.154",
|
||||
"164.132.205.154",
|
||||
"164.132.205.154",
|
||||
"164.132.205.154",
|
||||
"164.132.205.154",
|
||||
};
|
||||
|
||||
using ( var list = new ServerList.IpList( ips ) )
|
||||
{
|
||||
var success = await list.RunQueryAsync();
|
||||
|
||||
Console.WriteLine( $"success {success}" );
|
||||
Console.WriteLine( $"Found {list.Responsive.Count} Responsive Servers" );
|
||||
Console.WriteLine( $"Found {list.Unresponsive.Count} Unresponsive Servers" );
|
||||
|
||||
Assert.AreNotEqual( list.Responsive.Count, 0 );
|
||||
|
||||
foreach ( var server in list.Responsive )
|
||||
{
|
||||
Console.WriteLine( $"[{server.Address}:{server.ConnectionPort}] - {server.Name}" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
106
Facepunch.Steamworks.Test/SteamMatchmakingTest.cs
Normal file
106
Facepunch.Steamworks.Test/SteamMatchmakingTest.cs
Normal file
@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public class SteamMatchmakingTest
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task LobbyList()
|
||||
{
|
||||
await CreateLobby();
|
||||
|
||||
var list = await SteamMatchmaking.LobbyList
|
||||
.RequestAsync();
|
||||
|
||||
if ( list == null )
|
||||
{
|
||||
Console.WriteLine( "No Lobbies Found!" );
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( var lobby in list )
|
||||
{
|
||||
Console.WriteLine( $"[{lobby.Id}] owned by {lobby.Owner} ({lobby.MemberCount}/{lobby.MaxMembers})" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task LobbyListWithAtLeastOne()
|
||||
{
|
||||
await CreateLobby();
|
||||
await LobbyList();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CreateLobby()
|
||||
{
|
||||
var lobbyr = await SteamMatchmaking.CreateLobbyAsync( 32 );
|
||||
if ( !lobbyr.HasValue )
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
var lobby = lobbyr.Value;
|
||||
lobby.SetPublic();
|
||||
lobby.SetData( "gametype", "sausage" );
|
||||
lobby.SetData( "dicks", "unlicked" );
|
||||
|
||||
Console.WriteLine( $"lobby: {lobby.Id}" );
|
||||
|
||||
foreach ( var entry in lobby.Data )
|
||||
{
|
||||
Console.WriteLine( $" - {entry.Key} {entry.Value}" );
|
||||
}
|
||||
|
||||
Console.WriteLine( $"members: {lobby.MemberCount}/{lobby.MaxMembers}" );
|
||||
|
||||
Console.WriteLine( $"Owner: {lobby.Owner}" );
|
||||
Console.WriteLine( $"Owner Is Local Player: {lobby.Owner.IsMe}" );
|
||||
|
||||
lobby.SendChatString( "Hello I Love Lobbies" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task LobbyChat()
|
||||
{
|
||||
SteamMatchmaking.OnChatMessage += ( lbby, member, message ) =>
|
||||
{
|
||||
Console.WriteLine( $"[{lbby}] {member}: {message}" );
|
||||
};
|
||||
|
||||
var lobbyr = await SteamMatchmaking.CreateLobbyAsync( 10 );
|
||||
if ( !lobbyr.HasValue )
|
||||
Assert.Fail();
|
||||
|
||||
var lobby = lobbyr.Value;
|
||||
lobby.SetPublic();
|
||||
lobby.SetData( "name", "Dave's Chat Room" );
|
||||
Console.WriteLine( $"lobby: {lobby.Id}" );
|
||||
|
||||
lobby.SendChatString( "Hello Friends, It's me - your big fat daddy" );
|
||||
|
||||
await Task.Delay( 50 );
|
||||
|
||||
lobby.SendChatString( "What? No love for daddy?" );
|
||||
|
||||
await Task.Delay( 500 );
|
||||
|
||||
lobby.SendChatString( "Okay I will LEAVE" );
|
||||
lobby.SendChatString( "BYE FOREVER" );
|
||||
|
||||
await Task.Delay( 1000 );
|
||||
|
||||
lobby.Leave();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
37
Facepunch.Steamworks.Test/SteamNetworkingTest.cs
Normal file
37
Facepunch.Steamworks.Test/SteamNetworkingTest.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public class SteamNetworkingTest
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task SendP2PPacket()
|
||||
{
|
||||
var sent = SteamNetworking.SendP2PPacket( SteamClient.SteamId, new byte[] { 1, 2, 3 } );
|
||||
Assert.IsTrue( sent );
|
||||
|
||||
while ( !SteamNetworking.IsP2PPacketAvailable() )
|
||||
{
|
||||
await Task.Delay( 10 );
|
||||
}
|
||||
|
||||
var packet = SteamNetworking.ReadP2PPacket();
|
||||
|
||||
Assert.IsTrue( packet.HasValue );
|
||||
|
||||
Assert.AreEqual( packet.Value.SteamId, SteamClient.SteamId );
|
||||
Assert.AreEqual( packet.Value.Data[1], 2 );
|
||||
Assert.AreEqual( packet.Value.Data.Length, 3 );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
183
Facepunch.Steamworks.Test/UgcEditor.cs
Normal file
183
Facepunch.Steamworks.Test/UgcEditor.cs
Normal file
@ -0,0 +1,183 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public class UgcEditor
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task CreateFile()
|
||||
{
|
||||
var result = await Ugc.Editor.NewCommunityFile
|
||||
.WithTitle( "Unit Test Created Item" )
|
||||
.WithDescription( "This item was created by Facepunch Steamworks unit tests.\n\n" +
|
||||
"It should have technically been deleted so you should never get to " +
|
||||
"read this unless something terrible has happened." )
|
||||
.WithTag( "Arsehole" )
|
||||
.WithTag( "Spiteful" )
|
||||
.WithTag( "Fat-Head" )
|
||||
.SubmitAsync();
|
||||
|
||||
Assert.IsTrue( result.Success );
|
||||
Assert.AreNotEqual( result.FileId.Value, 0 );
|
||||
|
||||
var deleted = await SteamUGC.DeleteFileAsync( result.FileId );
|
||||
Assert.IsTrue( deleted );
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CreateChineseFile()
|
||||
{
|
||||
string fileName = "这是我的项目";
|
||||
string description = "此项目由Facepunch Steamworks单元测试创建";
|
||||
|
||||
var result = await Ugc.Editor.NewCommunityFile
|
||||
.WithTitle( fileName )
|
||||
.WithDescription( description )
|
||||
.WithTag( "Arsehole" )
|
||||
.WithTag( "Spiteful" )
|
||||
.WithTag( "Fat-Head" )
|
||||
.SubmitAsync();
|
||||
|
||||
Console.WriteLine( $"Title: {fileName}" );
|
||||
Console.WriteLine( $"Description: {description}" );
|
||||
|
||||
Assert.IsTrue( result.Success );
|
||||
Assert.AreNotEqual( result.FileId.Value, 0 );
|
||||
|
||||
var file = await Steamworks.SteamUGC.QueryFileAsync( result.FileId );
|
||||
|
||||
Console.WriteLine( $"FileId: {result.FileId}" );
|
||||
Console.WriteLine( $"Title: {file.Value.Title}" );
|
||||
Console.WriteLine( $"Description: {file.Value.Description}" );
|
||||
|
||||
Assert.AreEqual( file.Value.Title, fileName );
|
||||
Assert.AreEqual( file.Value.Description, description );
|
||||
|
||||
var deleted = await SteamUGC.DeleteFileAsync( result.FileId );
|
||||
Assert.IsTrue( deleted );
|
||||
|
||||
}
|
||||
|
||||
class ProgressBar : IProgress<float>
|
||||
{
|
||||
float Value = 0;
|
||||
|
||||
public void Report( float value )
|
||||
{
|
||||
if ( Value >= value ) return;
|
||||
|
||||
Value = value;
|
||||
|
||||
Console.WriteLine( value );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task UploadBigishFile()
|
||||
{
|
||||
var created = Ugc.Editor.NewCommunityFile
|
||||
.WithTitle( "Unit Test Upload Item" )
|
||||
.WithDescription( "This item was created by Facepunch Steamworks unit tests.\n\n" +
|
||||
"It should have technically been deleted so you should never get to " +
|
||||
"read this unless something terrible has happened." )
|
||||
//.WithTag( "Apple" )
|
||||
//.WithTag( "Banana" )
|
||||
;
|
||||
|
||||
|
||||
// Make a folder
|
||||
var testFolder = new System.IO.DirectoryInfo( "WorkshopUpload" );
|
||||
if ( !testFolder.Exists ) testFolder.Create();
|
||||
|
||||
created = created.WithContent( testFolder.FullName );
|
||||
|
||||
// Upload a file of random bytes
|
||||
var rand = new Random();
|
||||
var testFile = new byte[1024 * 1024 * 32];
|
||||
rand.NextBytes( testFile );
|
||||
System.IO.File.WriteAllBytes( testFolder.FullName + "/testfile1.bin", testFile );
|
||||
|
||||
Console.WriteLine( testFolder.FullName );
|
||||
|
||||
try
|
||||
{
|
||||
var done = await created.SubmitAsync( new ProgressBar() );
|
||||
|
||||
Assert.IsTrue( done.Success );
|
||||
Console.WriteLine( "item.Id: {0}", done.FileId );
|
||||
|
||||
var deleted = await SteamUGC.DeleteFileAsync( done.FileId );
|
||||
Assert.IsTrue( deleted );
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.IO.File.Delete( testFolder.FullName + "/testfile.bin" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public async Task CreateAndThenEditFile()
|
||||
{
|
||||
PublishedFileId fileid;
|
||||
|
||||
//
|
||||
// Make a file
|
||||
//
|
||||
{
|
||||
var result = await Ugc.Editor.NewCommunityFile
|
||||
.WithTitle( "Unedited File" )
|
||||
.SubmitAsync();
|
||||
|
||||
Assert.IsTrue( result.Success );
|
||||
Assert.AreNotEqual( result.FileId.Value, 0 );
|
||||
|
||||
fileid = result.FileId;
|
||||
}
|
||||
|
||||
await Task.Delay( 1000 );
|
||||
|
||||
//
|
||||
// Edit it
|
||||
//
|
||||
{
|
||||
var editor = new Ugc.Editor( fileid );
|
||||
editor = editor.WithTitle( "An Edited File" );
|
||||
var result = await editor.SubmitAsync();
|
||||
|
||||
Assert.IsTrue( result.Success );
|
||||
Assert.AreEqual( result.FileId, fileid );
|
||||
}
|
||||
|
||||
await Task.Delay( 1000 );
|
||||
|
||||
//
|
||||
// Make sure the edited file matches
|
||||
//
|
||||
{
|
||||
var details = await SteamUGC.QueryFileAsync( fileid ) ?? throw new Exception( "Somethign went wrong" );
|
||||
Assert.AreEqual( details.Id, fileid );
|
||||
Assert.AreEqual( details.Title, "An Edited File" );
|
||||
}
|
||||
|
||||
//
|
||||
// Clean up
|
||||
//
|
||||
var deleted = await SteamUGC.DeleteFileAsync( fileid );
|
||||
Assert.IsTrue( deleted );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
131
Facepunch.Steamworks.Test/UgcQuery.cs
Normal file
131
Facepunch.Steamworks.Test/UgcQuery.cs
Normal file
@ -0,0 +1,131 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public class UgcQueryTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task QueryAll()
|
||||
{
|
||||
var q = Ugc.Query.All;
|
||||
|
||||
var result = await q.GetPageAsync( 1 );
|
||||
Assert.IsNotNull( result );
|
||||
|
||||
Console.WriteLine( $"ResultCount: {result?.ResultCount}" );
|
||||
Console.WriteLine( $"TotalCount: {result?.TotalCount}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task QueryWithTags()
|
||||
{
|
||||
var q = Ugc.Query.All
|
||||
.WithTag( "Version3" )
|
||||
.WithTag( "Hunting Bow" )
|
||||
.MatchAllTags();
|
||||
|
||||
var result = await q.GetPageAsync( 1 );
|
||||
Assert.IsNotNull( result );
|
||||
Assert.IsTrue( result?.ResultCount > 0 );
|
||||
|
||||
Console.WriteLine( $"ResultCount: {result?.ResultCount}" );
|
||||
Console.WriteLine( $"TotalCount: {result?.TotalCount}" );
|
||||
|
||||
foreach ( var entry in result.Value.Entries )
|
||||
{
|
||||
Assert.IsTrue( entry.HasTag( "Version3" ), "Has Tag Version3" );
|
||||
Assert.IsTrue( entry.HasTag( "Hunting Bow" ), "Has Tag HuntingBow" );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task QueryAllFromFriends()
|
||||
{
|
||||
var q = Ugc.Query.All
|
||||
.CreatedByFriends();
|
||||
|
||||
var result = await q.GetPageAsync( 1 );
|
||||
Assert.IsNotNull( result );
|
||||
|
||||
Console.WriteLine( $"ResultCount: {result?.ResultCount}" );
|
||||
Console.WriteLine( $"TotalCount: {result?.TotalCount}" );
|
||||
|
||||
foreach ( var entry in result.Value.Entries )
|
||||
{
|
||||
Console.WriteLine( $" {entry.Title}" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task QueryUserOwn()
|
||||
{
|
||||
var q = Ugc.Query.All
|
||||
.WhereUserPublished();
|
||||
|
||||
var result = await q.GetPageAsync( 1 );
|
||||
Assert.IsNotNull( result );
|
||||
|
||||
Console.WriteLine( $"ResultCount: {result?.ResultCount}" );
|
||||
Console.WriteLine( $"TotalCount: {result?.TotalCount}" );
|
||||
|
||||
foreach ( var entry in result.Value.Entries )
|
||||
{
|
||||
Console.WriteLine( $" {entry.Title}" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task QueryGarry()
|
||||
{
|
||||
var q = Ugc.Query.All
|
||||
.WhereUserPublished( 76561197960279927 );
|
||||
|
||||
var result = await q.GetPageAsync( 1 );
|
||||
Assert.IsNotNull( result );
|
||||
Assert.IsTrue( result?.ResultCount > 0 );
|
||||
|
||||
Console.WriteLine( $"ResultCount: {result?.ResultCount}" );
|
||||
Console.WriteLine( $"TotalCount: {result?.TotalCount}" );
|
||||
|
||||
foreach ( var entry in result.Value.Entries )
|
||||
{
|
||||
Console.WriteLine( $" {entry.Title}" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task QuerySpecificFile()
|
||||
{
|
||||
var item = await SteamUGC.QueryFileAsync( 1734427277 );
|
||||
|
||||
Assert.IsTrue( item.HasValue );
|
||||
Assert.IsNotNull( item.Value.Title );
|
||||
|
||||
Console.WriteLine( $"Title: {item?.Title}" );
|
||||
Console.WriteLine( $"Desc: {item?.Description}" );
|
||||
Console.WriteLine( $"Tags: {string.Join( ",", item?.Tags )}" );
|
||||
Console.WriteLine( $"Author: {item?.Owner.Name} [{item?.Owner.Id}]" );
|
||||
Console.WriteLine( $"PreviewImageUrl: {item?.PreviewImageUrl}" );
|
||||
Console.WriteLine( $"NumComments: {item?.NumComments}" );
|
||||
Console.WriteLine( $"Url: {item?.Url}" );
|
||||
Console.WriteLine( $"Directory: {item?.Directory}" );
|
||||
Console.WriteLine( $"IsInstalled: {item?.IsInstalled}" );
|
||||
Console.WriteLine( $"IsAcceptedForUse: {item?.IsAcceptedForUse}" );
|
||||
Console.WriteLine( $"IsPublic: {item?.IsPublic}" );
|
||||
Console.WriteLine( $"Created: {item?.Created}" );
|
||||
Console.WriteLine( $"Updated: {item?.Updated}" );
|
||||
Console.WriteLine( $"Score: {item?.Score}" );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
41
Facepunch.Steamworks.Test/UgcTest.cs
Normal file
41
Facepunch.Steamworks.Test/UgcTest.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public class UgcTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void Download()
|
||||
{
|
||||
SteamUGC.Download( 1717844711 );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetInformation()
|
||||
{
|
||||
var itemInfo = await Ugc.Item.GetAsync( 1720164672 );
|
||||
|
||||
Assert.IsTrue( itemInfo.HasValue );
|
||||
|
||||
Console.WriteLine( $"Title: {itemInfo?.Title}" );
|
||||
Console.WriteLine( $"IsInstalled: {itemInfo?.IsInstalled}" );
|
||||
Console.WriteLine( $"IsDownloading: {itemInfo?.IsDownloading}" );
|
||||
Console.WriteLine( $"IsDownloadPending: {itemInfo?.IsDownloadPending}" );
|
||||
Console.WriteLine( $"IsSubscribed: {itemInfo?.IsSubscribed}" );
|
||||
Console.WriteLine( $"NeedsUpdate: {itemInfo?.NeedsUpdate}" );
|
||||
Console.WriteLine( $"Description: {itemInfo?.Description}" );
|
||||
Console.WriteLine( $"Owner: {itemInfo?.Owner}" );
|
||||
Console.WriteLine( $"Score: {itemInfo?.Score}" );
|
||||
Console.WriteLine( $"PreviewImageUrl: {itemInfo?.PreviewImageUrl}" );
|
||||
}
|
||||
}
|
||||
}
|
222
Facepunch.Steamworks.Test/UserStatsTest.cs
Normal file
222
Facepunch.Steamworks.Test/UserStatsTest.cs
Normal file
@ -0,0 +1,222 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Steamworks.Data;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public class UserStatsTest
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task AchievementList()
|
||||
{
|
||||
foreach ( var a in SteamUserStats.Achievements )
|
||||
{
|
||||
Console.WriteLine( $"{a.Identifier}" );
|
||||
Console.WriteLine( $" a.State: {a.State}" );
|
||||
Console.WriteLine( $" a.UnlockTime: {a.UnlockTime}" );
|
||||
Console.WriteLine( $" a.Name: {a.Name}" );
|
||||
Console.WriteLine( $" a.Description: {a.Description}" );
|
||||
Console.WriteLine( $" a.GlobalUnlocked: {a.GlobalUnlocked}" );
|
||||
|
||||
var icon = await a.GetIconAsync();
|
||||
|
||||
Console.WriteLine( $" a.Icon: {icon}" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task PlayerCountAsync()
|
||||
{
|
||||
var players = await SteamUserStats.PlayerCountAsync();
|
||||
Assert.AreNotEqual( players, -1 );
|
||||
Console.WriteLine( $"players: {players}" );
|
||||
}
|
||||
|
||||
public async Task StoreStats()
|
||||
{
|
||||
var result = Result.NotSettled;
|
||||
|
||||
SteamUserStats.OnUserStatsStored += ( r ) =>
|
||||
{
|
||||
result = r;
|
||||
};
|
||||
|
||||
SteamUserStats.StoreStats();
|
||||
|
||||
while ( result == Result.NotSettled )
|
||||
{
|
||||
await Task.Delay( 10 );
|
||||
}
|
||||
|
||||
Assert.AreEqual( result, Result.OK );
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CreateLeaderboard()
|
||||
{
|
||||
var leaderboard = await SteamUserStats.FindOrCreateLeaderboardAsync( "Testleaderboard", Data.LeaderboardSort.Ascending, Data.LeaderboardDisplay.Numeric );
|
||||
|
||||
Assert.IsTrue( leaderboard.HasValue );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task FindLeaderboard()
|
||||
{
|
||||
var leaderboard = await SteamUserStats.FindLeaderboardAsync( "Testleaderboard" );
|
||||
Assert.IsTrue( leaderboard.HasValue );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task SubmitScore()
|
||||
{
|
||||
var leaderboard = await SteamUserStats.FindLeaderboardAsync( "Testleaderboard" );
|
||||
Assert.IsTrue( leaderboard.HasValue );
|
||||
|
||||
var result = await leaderboard.Value.SubmitScoreAsync( 576 );
|
||||
Assert.IsTrue( result.HasValue );
|
||||
|
||||
Console.WriteLine( $"result.Changed: {result?.Changed}" );
|
||||
Console.WriteLine( $"result.OldGlobalRank: {result?.OldGlobalRank}" );
|
||||
Console.WriteLine( $"result.NewGlobalRank: {result?.NewGlobalRank}" );
|
||||
Console.WriteLine( $"result.RankChange: {result?.RankChange}" );
|
||||
Console.WriteLine( $"result.Score: {result?.Score}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ReplaceScore()
|
||||
{
|
||||
var leaderboard = await SteamUserStats.FindLeaderboardAsync( "Testleaderboard" );
|
||||
Assert.IsTrue( leaderboard.HasValue );
|
||||
|
||||
var result = await leaderboard.Value.ReplaceScore( 576 );
|
||||
Assert.IsTrue( result.HasValue );
|
||||
|
||||
Console.WriteLine( $"result.Changed: {result?.Changed}" );
|
||||
Console.WriteLine( $"result.OldGlobalRank: {result?.OldGlobalRank}" );
|
||||
Console.WriteLine( $"result.NewGlobalRank: {result?.NewGlobalRank}" );
|
||||
Console.WriteLine( $"result.RankChange: {result?.RankChange}" );
|
||||
Console.WriteLine( $"result.Score: {result?.Score}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetScoresFromFriends()
|
||||
{
|
||||
var leaderboard = await SteamUserStats.FindLeaderboardAsync( "Testleaderboard" );
|
||||
|
||||
var friendScores = await leaderboard.Value.GetScoresFromFriendsAsync();
|
||||
|
||||
foreach ( var e in friendScores )
|
||||
{
|
||||
Console.WriteLine( $"{e.GlobalRank}: {e.Score} {e.User}" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetScoresAroundUserAsync()
|
||||
{
|
||||
var leaderboard = await SteamUserStats.FindLeaderboardAsync( "Testleaderboard" );
|
||||
Assert.IsTrue( leaderboard.HasValue );
|
||||
|
||||
for ( int i = 1; i < 10; i++ )
|
||||
{
|
||||
// Get entries around user
|
||||
var relativeScores = await leaderboard.Value.GetScoresAroundUserAsync( -i, i );
|
||||
Assert.IsNotNull( relativeScores );
|
||||
|
||||
Console.WriteLine( $"" );
|
||||
Console.WriteLine( $"Relative Scores:" );
|
||||
foreach ( var e in relativeScores )
|
||||
{
|
||||
Console.WriteLine( $"{e.GlobalRank}: {e.Score} {e.User}" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetScoresAsync()
|
||||
{
|
||||
var leaderboard = await SteamUserStats.FindLeaderboardAsync( "Testleaderboard" );
|
||||
Assert.IsTrue( leaderboard.HasValue );
|
||||
|
||||
// Get top 20 global scores
|
||||
var globalsScores = await leaderboard.Value.GetScoresAsync( 20 );
|
||||
Assert.IsNotNull( globalsScores );
|
||||
|
||||
Console.WriteLine( $"" );
|
||||
Console.WriteLine( $"Global Scores:" );
|
||||
foreach ( var e in globalsScores )
|
||||
{
|
||||
Console.WriteLine( $"{e.GlobalRank}: {e.Score} {e.User}" );
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetStatInt()
|
||||
{
|
||||
var deaths = new Stat( "deaths" );
|
||||
Console.WriteLine( $"{deaths.Name} {deaths.GetInt()} times" );
|
||||
Console.WriteLine( $"{deaths.Name} {deaths.GetFloat()} times" );
|
||||
|
||||
Assert.AreNotEqual( 0, deaths.GetInt() );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetFriendStats()
|
||||
{
|
||||
var friend = new Friend( 76561197965732579 ); // Hezzy
|
||||
|
||||
// Download stats
|
||||
var status = await friend.RequestUserStatsAsync();
|
||||
Assert.AreNotEqual( false, status );
|
||||
|
||||
var deaths = friend.GetStatInt( "deaths" );
|
||||
|
||||
Console.WriteLine( $"Hezzy has died {deaths} times" );
|
||||
|
||||
Assert.AreNotEqual( 0, deaths );
|
||||
|
||||
var unlocked = friend.GetAchievement( "COLLECT_100_WOOD" );
|
||||
Assert.AreNotEqual( false, unlocked );
|
||||
|
||||
var when = friend.GetAchievementUnlockTime( "COLLECT_100_WOOD" );
|
||||
Assert.AreNotEqual( when, DateTime.MinValue );
|
||||
|
||||
Console.WriteLine( $"Hezzy unlocked COLLECT_100_WOOD {when}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetStatGlobalInt()
|
||||
{
|
||||
var deaths = new Stat( "deaths" );
|
||||
await deaths.GetGlobalIntDaysAsync( 5 );
|
||||
|
||||
var totalStartups = deaths.GetGlobalInt();
|
||||
Assert.AreNotEqual( 0, totalStartups );
|
||||
Console.WriteLine( $"Rust has had {totalStartups} deaths" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetStatGlobalHistoryInt()
|
||||
{
|
||||
var deaths = new Stat( "deaths" );
|
||||
|
||||
var history = await deaths.GetGlobalIntDaysAsync( 10 );
|
||||
Assert.AreNotEqual( 0, history.Length );
|
||||
|
||||
for ( int i=0; i< history.Length; i++ )
|
||||
{
|
||||
Console.WriteLine( $"{i} : {history[i]}" );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
191
Facepunch.Steamworks.Test/UserTest.cs
Normal file
191
Facepunch.Steamworks.Test/UserTest.cs
Normal file
@ -0,0 +1,191 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public class UserTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void GetVoice()
|
||||
{
|
||||
using ( var stream = new MemoryStream() )
|
||||
{
|
||||
int compressed = 0;
|
||||
|
||||
SteamUser.VoiceRecord = true;
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
|
||||
while ( sw.Elapsed.TotalSeconds < 3 )
|
||||
{
|
||||
System.Threading.Thread.Sleep( 10 );
|
||||
compressed += SteamUser.ReadVoiceData( stream );
|
||||
}
|
||||
|
||||
Assert.AreEqual( compressed, stream.Length );
|
||||
Console.WriteLine( $"compressed: {compressed}", compressed );
|
||||
Console.WriteLine( $"stream.Length: {stream.Length}", stream.Length );
|
||||
}
|
||||
}
|
||||
[TestMethod]
|
||||
public void OptimalSampleRate()
|
||||
{
|
||||
var rate = SteamUser.OptimalSampleRate;
|
||||
Assert.AreNotEqual( rate, 0 );
|
||||
Console.WriteLine( $"User.OptimalSampleRate: {SteamUser.OptimalSampleRate}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsLoggedOn()
|
||||
{
|
||||
Assert.AreNotEqual( false, SteamClient.IsLoggedOn );
|
||||
Console.WriteLine( $"User.IsLoggedOn: {SteamClient.IsLoggedOn}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SteamID()
|
||||
{
|
||||
Assert.AreNotEqual( 0, SteamClient.SteamId.Value );
|
||||
Console.WriteLine( $"User.SteamID: {SteamClient.SteamId.Value}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AuthSession()
|
||||
{
|
||||
var ticket = SteamUser.GetAuthSessionTicket( SteamClient.SteamId );
|
||||
|
||||
Assert.AreNotEqual( 0, ticket.Handle );
|
||||
Assert.AreNotEqual( 0, ticket.Data.Length );
|
||||
Console.WriteLine( $"ticket.Handle: {ticket.Handle}" );
|
||||
Console.WriteLine( $"ticket.Data: { string.Join( "", ticket.Data.Select( x => x.ToString( "x" ) ) ) }" );
|
||||
|
||||
var result = SteamUser.BeginAuthSession( ticket.Data, SteamClient.SteamId );
|
||||
Console.WriteLine( $"result: { result }" );
|
||||
Assert.AreEqual( result, BeginAuthResult.OK );
|
||||
|
||||
SteamUser.EndAuthSession( SteamClient.SteamId );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task AuthSessionAsync()
|
||||
{
|
||||
var ticket = await SteamUser.GetAuthSessionTicketAsync( SteamClient.SteamId, 5.0 );
|
||||
|
||||
Assert.AreNotEqual( 0, ticket.Handle );
|
||||
Assert.AreNotEqual( 0, ticket.Data.Length );
|
||||
Console.WriteLine( $"ticket.Handle: {ticket.Handle}" );
|
||||
Console.WriteLine( $"ticket.Data: { string.Join( "", ticket.Data.Select( x => x.ToString( "x" ) ) ) }" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task AuthTicketForWebApiAsync()
|
||||
{
|
||||
var ticket = await SteamUser.GetAuthTicketForWebApiAsync( "Test" );
|
||||
|
||||
Assert.AreNotEqual( 0, ticket.Handle );
|
||||
Assert.AreNotEqual( 0, ticket.Data.Length );
|
||||
Console.WriteLine( $"ticket.Handle: {ticket.Handle}" );
|
||||
Console.WriteLine( $"ticket.Data: { string.Join( "", ticket.Data.Select( x => x.ToString( "x" ) ) ) }" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SteamLevel()
|
||||
{
|
||||
Assert.AreNotEqual( 0, SteamUser.SteamLevel );
|
||||
Console.WriteLine( $"User.SteamLevel: {SteamUser.SteamLevel}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Name()
|
||||
{
|
||||
Console.WriteLine( $"SteamClient.Name: {SteamClient.Name}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetStoreAuthUrlAsync()
|
||||
{
|
||||
var rustskins = await SteamUser.GetStoreAuthUrlAsync( "https://store.steampowered.com/itemstore/252490/" );
|
||||
|
||||
Assert.IsNotNull( rustskins );
|
||||
Console.WriteLine( $"rustskins: {rustskins}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsPhoneVerified()
|
||||
{
|
||||
Console.WriteLine( $"User.IsPhoneVerified: {SteamUser.IsPhoneVerified}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsTwoFactorEnabled()
|
||||
{
|
||||
Console.WriteLine( $"User.IsTwoFactorEnabled: {SteamUser.IsTwoFactorEnabled}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsPhoneIdentifying()
|
||||
{
|
||||
Console.WriteLine( $"User.IsPhoneIdentifying: {SteamUser.IsPhoneIdentifying}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsPhoneRequiringVerification()
|
||||
{
|
||||
Console.WriteLine( $"User.IsPhoneRequiringVerification: {SteamUser.IsPhoneRequiringVerification}" );
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public async Task RequestEncryptedAppTicketAsyncWithData()
|
||||
{
|
||||
for ( int i=0; i<10; i++ )
|
||||
{
|
||||
var data = await SteamUser.RequestEncryptedAppTicketAsync( new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 } );
|
||||
|
||||
if ( data == null )
|
||||
{
|
||||
Console.WriteLine( $"Attempt {i}: Returned null.. waiting 1 seconds" );
|
||||
await Task.Delay( 10000 );
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine( $"data: {BitConverter.ToString( data )}" );
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task RequestEncryptedAppTicketAsync()
|
||||
{
|
||||
for ( int i = 0; i < 6; i++ )
|
||||
{
|
||||
var data = await SteamUser.RequestEncryptedAppTicketAsync();
|
||||
|
||||
if ( data == null )
|
||||
{
|
||||
Console.WriteLine( $"Attempt {i}: Returned null.. waiting 1 seconds" );
|
||||
await Task.Delay( 10000 );
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine( $"data: {BitConverter.ToString( data )}" );
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
118
Facepunch.Steamworks.Test/UtilsTest.cs
Normal file
118
Facepunch.Steamworks.Test/UtilsTest.cs
Normal file
@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
[TestClass]
|
||||
[DeploymentItem( "steam_api64.dll" )]
|
||||
[DeploymentItem( "steam_api.dll" )]
|
||||
public class UtilsTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void SecondsSinceAppActive()
|
||||
{
|
||||
var time = SteamUtils.SecondsSinceAppActive;
|
||||
Console.WriteLine( $"{time}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SecondsSinceComputerActive()
|
||||
{
|
||||
var time = SteamUtils.SecondsSinceComputerActive;
|
||||
Console.WriteLine( $"{time}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ConnectedUniverse()
|
||||
{
|
||||
var u = SteamUtils.ConnectedUniverse;
|
||||
Console.WriteLine( $"{u}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SteamServerTime()
|
||||
{
|
||||
var time = SteamUtils.SteamServerTime;
|
||||
Console.WriteLine( $"{time}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IpCountry()
|
||||
{
|
||||
var cnt = SteamUtils.IpCountry;
|
||||
Console.WriteLine( $"{cnt}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UsingBatteryPower()
|
||||
{
|
||||
var cnt = SteamUtils.UsingBatteryPower;
|
||||
Console.WriteLine( $"{cnt}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CurrentBatteryPower()
|
||||
{
|
||||
var cnt = SteamUtils.CurrentBatteryPower;
|
||||
Console.WriteLine( $"{cnt}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AppId()
|
||||
{
|
||||
var cnt = SteamClient.AppId;
|
||||
|
||||
Assert.IsTrue( cnt.Value > 0 );
|
||||
|
||||
Console.WriteLine( $"{cnt.Value}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsOverlayEnabled()
|
||||
{
|
||||
var cnt = SteamUtils.IsOverlayEnabled;
|
||||
Console.WriteLine( $"{cnt}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CheckFileSignature()
|
||||
{
|
||||
var sig = await SteamUtils.CheckFileSignatureAsync( "hl2.exe" );
|
||||
Console.WriteLine( $"{sig}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void SteamUILanguage()
|
||||
{
|
||||
var cnt = SteamUtils.SteamUILanguage;
|
||||
Console.WriteLine( $"{cnt}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsSteamRunningInVR()
|
||||
{
|
||||
var cnt = SteamUtils.IsSteamRunningInVR;
|
||||
Console.WriteLine( $"{cnt}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IsSteamInBigPictureMode()
|
||||
{
|
||||
var cnt = SteamUtils.IsSteamInBigPictureMode;
|
||||
Console.WriteLine( $"{cnt}" );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void VrHeadsetStreaming()
|
||||
{
|
||||
var cnt = SteamUtils.VrHeadsetStreaming;
|
||||
Console.WriteLine( $"{cnt}" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,74 @@
|
||||
"In Game Actions"
|
||||
{
|
||||
"actions"
|
||||
{
|
||||
"InGameControls"
|
||||
{
|
||||
"title" "#Set_Ingame"
|
||||
"StickPadGyro"
|
||||
{
|
||||
"Move"
|
||||
{
|
||||
"title" "#Action_Move"
|
||||
"input_mode" "joystick_move"
|
||||
}
|
||||
"Camera"
|
||||
{
|
||||
"title" "#Action_Camera"
|
||||
"input_mode" "absolute_mouse"
|
||||
}
|
||||
}
|
||||
"AnalogTrigger"
|
||||
{
|
||||
"Throttle" "#Action_Throttle"
|
||||
}
|
||||
"Button"
|
||||
{
|
||||
"fire" "#Action_Fire"
|
||||
"Jump" "#Action_Jump"
|
||||
"pause_menu" "#Action_Menu"
|
||||
}
|
||||
}
|
||||
"MenuControls"
|
||||
{
|
||||
"title" "#Set_Menu"
|
||||
"StickPadGyro"
|
||||
{
|
||||
}
|
||||
"AnalogTrigger"
|
||||
{
|
||||
}
|
||||
"Button"
|
||||
{
|
||||
"menu_up" "#Menu_Up"
|
||||
"menu_down" "#Menu_Down"
|
||||
"menu_left" "#Menu_Left"
|
||||
"menu_right" "#Menu_Right"
|
||||
"menu_select" "#Menu_Select"
|
||||
"menu_cancel" "#Menu_Cancel"
|
||||
"pause_menu" "#Action_ReturnToGame"
|
||||
}
|
||||
}
|
||||
}
|
||||
"localization"
|
||||
{
|
||||
"english"
|
||||
{
|
||||
"Set_Ingame" "In-Game Controls"
|
||||
"Set_Menu" "Menu Controls"
|
||||
"Action_Move" "Movement"
|
||||
"Action_Camera" "Camera"
|
||||
"Action_Throttle" "Throttle"
|
||||
"Action_Fire" "Fire Weapon"
|
||||
"Action_Jump" "Jump"
|
||||
"Action_Menu" "Pause Menu"
|
||||
"Action_ReturnToGame" "Return To Game"
|
||||
"Menu_Up" "Up"
|
||||
"Menu_Down" "Down"
|
||||
"Menu_Left" "Left"
|
||||
"Menu_Right" "Right"
|
||||
"Menu_Select" "Select"
|
||||
"Menu_Cancel" "Cancel"
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
@ -1 +0,0 @@
|
||||
252490
|
Binary file not shown.
BIN
Facepunch.Steamworks.Test/bin/Debug/steamclient64.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Debug/steamclient64.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
Facepunch.Steamworks.Test/bin/Debug/tier0_s64.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Debug/tier0_s64.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
Facepunch.Steamworks.Test/bin/Debug/vstdlib_s64.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Debug/vstdlib_s64.dll
Normal file
Binary file not shown.
Binary file not shown.
@ -0,0 +1,74 @@
|
||||
"In Game Actions"
|
||||
{
|
||||
"actions"
|
||||
{
|
||||
"InGameControls"
|
||||
{
|
||||
"title" "#Set_Ingame"
|
||||
"StickPadGyro"
|
||||
{
|
||||
"Move"
|
||||
{
|
||||
"title" "#Action_Move"
|
||||
"input_mode" "joystick_move"
|
||||
}
|
||||
"Camera"
|
||||
{
|
||||
"title" "#Action_Camera"
|
||||
"input_mode" "absolute_mouse"
|
||||
}
|
||||
}
|
||||
"AnalogTrigger"
|
||||
{
|
||||
"Throttle" "#Action_Throttle"
|
||||
}
|
||||
"Button"
|
||||
{
|
||||
"fire" "#Action_Fire"
|
||||
"Jump" "#Action_Jump"
|
||||
"pause_menu" "#Action_Menu"
|
||||
}
|
||||
}
|
||||
"MenuControls"
|
||||
{
|
||||
"title" "#Set_Menu"
|
||||
"StickPadGyro"
|
||||
{
|
||||
}
|
||||
"AnalogTrigger"
|
||||
{
|
||||
}
|
||||
"Button"
|
||||
{
|
||||
"menu_up" "#Menu_Up"
|
||||
"menu_down" "#Menu_Down"
|
||||
"menu_left" "#Menu_Left"
|
||||
"menu_right" "#Menu_Right"
|
||||
"menu_select" "#Menu_Select"
|
||||
"menu_cancel" "#Menu_Cancel"
|
||||
"pause_menu" "#Action_ReturnToGame"
|
||||
}
|
||||
}
|
||||
}
|
||||
"localization"
|
||||
{
|
||||
"english"
|
||||
{
|
||||
"Set_Ingame" "In-Game Controls"
|
||||
"Set_Menu" "Menu Controls"
|
||||
"Action_Move" "Movement"
|
||||
"Action_Camera" "Camera"
|
||||
"Action_Throttle" "Throttle"
|
||||
"Action_Fire" "Fire Weapon"
|
||||
"Action_Jump" "Jump"
|
||||
"Action_Menu" "Pause Menu"
|
||||
"Action_ReturnToGame" "Return To Game"
|
||||
"Menu_Up" "Up"
|
||||
"Menu_Down" "Down"
|
||||
"Menu_Left" "Left"
|
||||
"Menu_Right" "Right"
|
||||
"Menu_Select" "Select"
|
||||
"Menu_Cancel" "Cancel"
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
252490
|
BIN
Facepunch.Steamworks.Test/bin/Release/steamclient.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Release/steamclient.dll
Normal file
Binary file not shown.
BIN
Facepunch.Steamworks.Test/bin/Release/steamclient64.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Release/steamclient64.dll
Normal file
Binary file not shown.
BIN
Facepunch.Steamworks.Test/bin/Release/tier0_s.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Release/tier0_s.dll
Normal file
Binary file not shown.
BIN
Facepunch.Steamworks.Test/bin/Release/tier0_s64.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Release/tier0_s64.dll
Normal file
Binary file not shown.
BIN
Facepunch.Steamworks.Test/bin/Release/vstdlib_s.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Release/vstdlib_s.dll
Normal file
Binary file not shown.
BIN
Facepunch.Steamworks.Test/bin/Release/vstdlib_s64.dll
Normal file
BIN
Facepunch.Steamworks.Test/bin/Release/vstdlib_s64.dll
Normal file
Binary file not shown.
6
Facepunch.Steamworks.Test/packages.config
Normal file
6
Facepunch.Steamworks.Test/packages.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="MSTest.TestAdapter" version="2.0.0-beta4" targetFramework="net46" />
|
||||
<package id="MSTest.TestFramework" version="2.0.0-beta4" targetFramework="net46" />
|
||||
<package id="Newtonsoft.Json" version="9.0.2-beta1" targetFramework="net452" />
|
||||
</packages>
|
BIN
Facepunch.Steamworks.Test/steam_api.dll
Normal file
BIN
Facepunch.Steamworks.Test/steam_api.dll
Normal file
Binary file not shown.
BIN
Facepunch.Steamworks.Test/steam_api64.dll
Normal file
BIN
Facepunch.Steamworks.Test/steam_api64.dll
Normal file
Binary file not shown.
@ -1,28 +1,107 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25123.0
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29009.5
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facepunch.Steamworks", "Facepunch.Steamworks\Facepunch.Steamworks.csproj", "{DC2D9FA9-F005-468F-8581-85C79F4E0034}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Generator", "Generator\Generator.csproj", "{B7225D11-2AAA-49D6-AE93-A73696EA35FE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facepunch.Steamworks.Test", "Facepunch.Steamworks.Test\Facepunch.Steamworks.Test.csproj", "{3F6183AD-D966-44F2-A6EB-42E61E591B49}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Facepunch.Steamworks.Win64", "Facepunch.Steamworks\Facepunch.Steamworks.Win64.csproj", "{8C73DA93-73AD-4445-9A2C-15D4A44337D3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Facepunch.Steamworks.Win32", "Facepunch.Steamworks\Facepunch.Steamworks.Win32.csproj", "{2D6247F6-8AB2-405F-A00E-3A364B808A55}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Facepunch.Steamworks.Posix", "Facepunch.Steamworks\Facepunch.Steamworks.Posix.csproj", "{C62FF421-BE44-4DB0-B99A-E13E007A30B9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facepunch.Steamworks.TestWin32", "Facepunch.Steamworks.Test\Facepunch.Steamworks.TestWin32.csproj", "{3F6183AD-D966-44F2-A6EB-42E61E591B49}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Facepunch.Steamworks.TestWin64", "Facepunch.Steamworks.Test\Facepunch.Steamworks.TestWin64.csproj", "{165081E3-BD96-404B-B83E-A635F1AF7CDE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{DC2D9FA9-F005-468F-8581-85C79F4E0034}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DC2D9FA9-F005-468F-8581-85C79F4E0034}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DC2D9FA9-F005-468F-8581-85C79F4E0034}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DC2D9FA9-F005-468F-8581-85C79F4E0034}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B7225D11-2AAA-49D6-AE93-A73696EA35FE}.Release|x86.Build.0 = Release|Any CPU
|
||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8C73DA93-73AD-4445-9A2C-15D4A44337D3}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2D6247F6-8AB2-405F-A00E-3A364B808A55}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C62FF421-BE44-4DB0-B99A-E13E007A30B9}.Release|x86.Build.0 = Release|Any CPU
|
||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Debug|x64.Build.0 = Debug|x64
|
||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Debug|x86.Build.0 = Debug|x86
|
||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Release|x64.ActiveCfg = Release|x64
|
||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Release|x64.Build.0 = Release|x64
|
||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Release|x86.ActiveCfg = Release|x86
|
||||
{3F6183AD-D966-44F2-A6EB-42E61E591B49}.Release|x86.Build.0 = Release|x86
|
||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Debug|x64.Build.0 = Debug|x64
|
||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Debug|x86.Build.0 = Debug|x86
|
||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Release|x64.ActiveCfg = Release|x64
|
||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Release|x64.Build.0 = Release|x64
|
||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Release|x86.ActiveCfg = Release|x86
|
||||
{165081E3-BD96-404B-B83E-A635F1AF7CDE}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {506FC2EC-38D1-45E2-BAE8-D61584162F7D}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@ -1,146 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Facepunch.Steamworks.Interop;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public class BaseSteamworks : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Current running program's AppId
|
||||
/// </summary>
|
||||
public uint AppId { get; internal set; }
|
||||
|
||||
public Networking Networking { get; internal set; }
|
||||
public Inventory Inventory { get; internal set; }
|
||||
public Workshop Workshop { get; internal set; }
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
foreach ( var d in Disposables )
|
||||
{
|
||||
d.Dispose();
|
||||
}
|
||||
Disposables.Clear();
|
||||
|
||||
Workshop.Dispose();
|
||||
Workshop = null;
|
||||
|
||||
Inventory.Dispose();
|
||||
Inventory = null;
|
||||
|
||||
Networking.Dispose();
|
||||
Networking = null;
|
||||
|
||||
if ( native != null )
|
||||
{
|
||||
native.Dispose();
|
||||
native = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetupCommonInterfaces()
|
||||
{
|
||||
Networking = new Steamworks.Networking( this, native.networking );
|
||||
Inventory = new Steamworks.Inventory( native.inventory, IsGameServer );
|
||||
Workshop = new Steamworks.Workshop( this, native.ugc, native.remoteStorage );
|
||||
}
|
||||
|
||||
public bool IsValid
|
||||
{
|
||||
get { return native != null; }
|
||||
}
|
||||
|
||||
internal Interop.NativeInterface native;
|
||||
internal virtual bool IsGameServer { get { return false; } }
|
||||
|
||||
private List<IDisposable> Disposables = new List<IDisposable>();
|
||||
|
||||
public enum MessageType : int
|
||||
{
|
||||
Message = 0,
|
||||
Warning = 1
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called with a message from Steam
|
||||
/// </summary>
|
||||
public Action<MessageType, string> OnMessage;
|
||||
|
||||
/// <summary>
|
||||
/// Global callback type
|
||||
/// </summary>
|
||||
internal void AddCallback<T, TSmall>( Action<T> Callback, int id )
|
||||
{
|
||||
var callback = new Callback<T, TSmall>( IsGameServer, id, Callback );
|
||||
Disposables.Add( callback );
|
||||
}
|
||||
|
||||
internal void AddCallback<T>( Action<T> Callback, int id )
|
||||
{
|
||||
AddCallback<T, T>( Callback, id );
|
||||
}
|
||||
|
||||
public Action OnUpdate;
|
||||
|
||||
|
||||
public virtual void Update()
|
||||
{
|
||||
RunCallbackQueue();
|
||||
|
||||
Inventory.Update();
|
||||
Networking.Update();
|
||||
|
||||
if ( OnUpdate != null )
|
||||
OnUpdate();
|
||||
}
|
||||
|
||||
List<CallResult> Callbacks = new List<CallResult>();
|
||||
|
||||
/// <summary>
|
||||
/// Call results are results to specific actions
|
||||
/// </summary>
|
||||
internal void AddCallResult( CallResult call )
|
||||
{
|
||||
if ( call == null ) throw new ArgumentNullException( "call" );
|
||||
|
||||
if ( FinishCallback( call ) )
|
||||
return;
|
||||
|
||||
Callbacks.Add( call );
|
||||
}
|
||||
|
||||
void RunCallbackQueue()
|
||||
{
|
||||
for ( int i=0; i< Callbacks.Count(); i++ )
|
||||
{
|
||||
if ( !FinishCallback( Callbacks[i] ) )
|
||||
continue;
|
||||
|
||||
Callbacks.RemoveAt( i );
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
bool FinishCallback( CallResult call )
|
||||
{
|
||||
bool failed = true;
|
||||
|
||||
if ( !native.utils.IsAPICallCompleted( call.Handle, ref failed ) )
|
||||
return false;
|
||||
|
||||
if ( failed )
|
||||
{
|
||||
//
|
||||
// TODO - failure reason?
|
||||
//
|
||||
return true;
|
||||
}
|
||||
|
||||
call.Run( native.utils );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
98
Facepunch.Steamworks/Callbacks/CallResult.cs
Normal file
98
Facepunch.Steamworks/Callbacks/CallResult.cs
Normal file
@ -0,0 +1,98 @@
|
||||
using Steamworks.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
/// <summary>
|
||||
/// An awaitable version of a SteamAPICall_t
|
||||
/// </summary>
|
||||
internal struct CallResult<T> : INotifyCompletion where T : struct, ICallbackData
|
||||
{
|
||||
SteamAPICall_t call;
|
||||
ISteamUtils utils;
|
||||
bool server;
|
||||
|
||||
public CallResult( SteamAPICall_t call, bool server )
|
||||
{
|
||||
this.call = call;
|
||||
this.server = server;
|
||||
|
||||
utils = (server ? SteamUtils.InterfaceServer : SteamUtils.InterfaceClient) as ISteamUtils;
|
||||
|
||||
if ( utils == null )
|
||||
utils = SteamUtils.Interface as ISteamUtils;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This gets called if IsComplete returned false on the first call.
|
||||
/// The Action "continues" the async call. We pass it to the Dispatch
|
||||
/// to be called when the callback returns.
|
||||
/// </summary>
|
||||
public void OnCompleted( Action continuation )
|
||||
{
|
||||
if (IsCompleted)
|
||||
continuation();
|
||||
else
|
||||
Dispatch.OnCallComplete<T>(call, continuation, server);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the result. This is called internally by the async shit.
|
||||
/// </summary>
|
||||
public T? GetResult()
|
||||
{
|
||||
bool failed = false;
|
||||
if ( !utils.IsAPICallCompleted( call, ref failed ) || failed )
|
||||
return null;
|
||||
|
||||
var t = default( T );
|
||||
var size = t.DataSize;
|
||||
var ptr = Marshal.AllocHGlobal( size );
|
||||
|
||||
try
|
||||
{
|
||||
if ( !utils.GetAPICallResult( call, ptr, size, (int)t.CallbackType, ref failed ) || failed )
|
||||
{
|
||||
Dispatch.OnDebugCallback?.Invoke( t.CallbackType, "!GetAPICallResult or failed", server );
|
||||
return null;
|
||||
}
|
||||
|
||||
Dispatch.OnDebugCallback?.Invoke( t.CallbackType, Dispatch.CallbackToString( t.CallbackType, ptr, size ), server );
|
||||
|
||||
return ((T)Marshal.PtrToStructure( ptr, typeof( T ) ));
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal( ptr );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return true if complete or failed
|
||||
/// </summary>
|
||||
public bool IsCompleted
|
||||
{
|
||||
get
|
||||
{
|
||||
bool failed = false;
|
||||
if ( utils.IsAPICallCompleted( call, ref failed ) || failed )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is what makes this struct awaitable
|
||||
/// </summary>
|
||||
internal CallResult<T> GetAwaiter()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
17
Facepunch.Steamworks/Callbacks/ICallbackData.cs
Normal file
17
Facepunch.Steamworks/Callbacks/ICallbackData.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using Steamworks.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
/// <summary>
|
||||
/// Gives us a generic way to get the CallbackId of structs
|
||||
/// </summary>
|
||||
internal interface ICallbackData
|
||||
{
|
||||
CallbackType CallbackType { get; }
|
||||
int DataSize { get; }
|
||||
}
|
||||
}
|
@ -1,124 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Facepunch.Steamworks.Callbacks
|
||||
{
|
||||
internal static class Index
|
||||
{
|
||||
internal const int User = 100;
|
||||
internal const int Networking = 1200;
|
||||
internal const int RemoteStorage = 1300;
|
||||
internal const int UGC = 3400;
|
||||
}
|
||||
|
||||
public enum Result : int
|
||||
{
|
||||
OK = 1, // success
|
||||
Fail = 2, // generic failure
|
||||
NoConnection = 3, // no/failed network connection
|
||||
// k_EResultNoConnectionRetry = 4, // OBSOLETE - removed
|
||||
InvalidPassword = 5, // password/ticket is invalid
|
||||
LoggedInElsewhere = 6, // same user logged in elsewhere
|
||||
InvalidProtocolVer = 7, // protocol version is incorrect
|
||||
InvalidParam = 8, // a parameter is incorrect
|
||||
FileNotFound = 9, // file was not found
|
||||
Busy = 10, // called method busy - action not taken
|
||||
InvalidState = 11, // called object was in an invalid state
|
||||
InvalidName = 12, // name is invalid
|
||||
InvalidEmail = 13, // email is invalid
|
||||
DuplicateName = 14, // name is not unique
|
||||
AccessDenied = 15, // access is denied
|
||||
Timeout = 16, // operation timed out
|
||||
Banned = 17, // VAC2 banned
|
||||
AccountNotFound = 18, // account not found
|
||||
InvalidSteamID = 19, // steamID is invalid
|
||||
ServiceUnavailable = 20, // The requested service is currently unavailable
|
||||
NotLoggedOn = 21, // The user is not logged on
|
||||
Pending = 22, // Request is pending (may be in process, or waiting on third party)
|
||||
EncryptionFailure = 23, // Encryption or Decryption failed
|
||||
InsufficientPrivilege = 24, // Insufficient privilege
|
||||
LimitExceeded = 25, // Too much of a good thing
|
||||
Revoked = 26, // Access has been revoked (used for revoked guest passes)
|
||||
Expired = 27, // License/Guest pass the user is trying to access is expired
|
||||
AlreadyRedeemed = 28, // Guest pass has already been redeemed by account, cannot be acked again
|
||||
DuplicateRequest = 29, // The request is a duplicate and the action has already occurred in the past, ignored this time
|
||||
AlreadyOwned = 30, // All the games in this guest pass redemption request are already owned by the user
|
||||
IPNotFound = 31, // IP address not found
|
||||
PersistFailed = 32, // failed to write change to the data store
|
||||
LockingFailed = 33, // failed to acquire access lock for this operation
|
||||
LogonSessionReplaced = 34,
|
||||
ConnectFailed = 35,
|
||||
HandshakeFailed = 36,
|
||||
IOFailure = 37,
|
||||
RemoteDisconnect = 38,
|
||||
ShoppingCartNotFound = 39, // failed to find the shopping cart requested
|
||||
Blocked = 40, // a user didn't allow it
|
||||
Ignored = 41, // target is ignoring sender
|
||||
NoMatch = 42, // nothing matching the request found
|
||||
AccountDisabled = 43,
|
||||
ServiceReadOnly = 44, // this service is not accepting content changes right now
|
||||
AccountNotFeatured = 45, // account doesn't have value, so this feature isn't available
|
||||
AdministratorOK = 46, // allowed to take this action, but only because requester is admin
|
||||
ContentVersion = 47, // A Version mismatch in content transmitted within the Steam protocol.
|
||||
TryAnotherCM = 48, // The current CM can't service the user making a request, user should try another.
|
||||
PasswordRequiredToKickSession = 49,// You are already logged in elsewhere, this cached credential login has failed.
|
||||
AlreadyLoggedInElsewhere = 50, // You are already logged in elsewhere, you must wait
|
||||
Suspended = 51, // Long running operation (content download) suspended/paused
|
||||
Cancelled = 52, // Operation canceled (typically by user: content download)
|
||||
DataCorruption = 53, // Operation canceled because data is ill formed or unrecoverable
|
||||
DiskFull = 54, // Operation canceled - not enough disk space.
|
||||
RemoteCallFailed = 55, // an remote call or IPC call failed
|
||||
PasswordUnset = 56, // Password could not be verified as it's unset server side
|
||||
ExternalAccountUnlinked = 57, // External account (PSN, Facebook...) is not linked to a Steam account
|
||||
PSNTicketInvalid = 58, // PSN ticket was invalid
|
||||
ExternalAccountAlreadyLinked = 59, // External account (PSN, Facebook...) is already linked to some other account, must explicitly request to replace/delete the link first
|
||||
RemoteFileConflict = 60, // The sync cannot resume due to a conflict between the local and remote files
|
||||
IllegalPassword = 61, // The requested new password is not legal
|
||||
SameAsPreviousValue = 62, // new value is the same as the old one ( secret question and answer )
|
||||
AccountLogonDenied = 63, // account login denied due to 2nd factor authentication failure
|
||||
CannotUseOldPassword = 64, // The requested new password is not legal
|
||||
InvalidLoginAuthCode = 65, // account login denied due to auth code invalid
|
||||
AccountLogonDeniedNoMail = 66, // account login denied due to 2nd factor auth failure - and no mail has been sent
|
||||
HardwareNotCapableOfIPT = 67, //
|
||||
IPTInitError = 68, //
|
||||
ParentalControlRestricted = 69, // operation failed due to parental control restrictions for current user
|
||||
FacebookQueryError = 70, // Facebook query returned an error
|
||||
ExpiredLoginAuthCode = 71, // account login denied due to auth code expired
|
||||
IPLoginRestrictionFailed = 72,
|
||||
AccountLockedDown = 73,
|
||||
AccountLogonDeniedVerifiedEmailRequired = 74,
|
||||
NoMatchingURL = 75,
|
||||
BadResponse = 76, // parse failure, missing field, etc.
|
||||
RequirePasswordReEntry = 77, // The user cannot complete the action until they re-enter their password
|
||||
ValueOutOfRange = 78, // the value entered is outside the acceptable range
|
||||
UnexpectedError = 79, // something happened that we didn't expect to ever happen
|
||||
Disabled = 80, // The requested service has been configured to be unavailable
|
||||
InvalidCEGSubmission = 81, // The set of files submitted to the CEG server are not valid !
|
||||
RestrictedDevice = 82, // The device being used is not allowed to perform this action
|
||||
RegionLocked = 83, // The action could not be complete because it is region restricted
|
||||
RateLimitExceeded = 84, // Temporary rate limit exceeded, try again later, different from k_EResultLimitExceeded which may be permanent
|
||||
AccountLoginDeniedNeedTwoFactor = 85, // Need two-factor code to login
|
||||
ItemDeleted = 86, // The thing we're trying to access has been deleted
|
||||
AccountLoginDeniedThrottle = 87, // login attempt failed, try to throttle response to possible attacker
|
||||
TwoFactorCodeMismatch = 88, // two factor code mismatch
|
||||
TwoFactorActivationCodeMismatch = 89, // activation code for two-factor didn't match
|
||||
AccountAssociatedToMultiplePartners = 90, // account has been associated with multiple partners
|
||||
NotModified = 91, // data not modified
|
||||
NoMobileDevice = 92, // the account does not have a mobile device associated with it
|
||||
TimeNotSynced = 93, // the time presented is out of range or tolerance
|
||||
SmsCodeFailed = 94, // SMS code failure (no match, none pending, etc.)
|
||||
AccountLimitExceeded = 95, // Too many accounts access this resource
|
||||
AccountActivityLimitExceeded = 96, // Too many changes to this account
|
||||
PhoneActivityLimitExceeded = 97, // Too many changes to this phone
|
||||
RefundToWallet = 98, // Cannot refund to payment method, must use wallet
|
||||
EmailSendFailure = 99, // Cannot send an email
|
||||
NotSettled = 100, // Can't perform operation till payment has settled
|
||||
NeedCaptcha = 101, // Needs to provide a valid captcha
|
||||
GSLTDenied = 102, // a game server login token owned by this token's owner has been banned
|
||||
GSOwnerDenied = 103, // game server owner is denied for other reason (account lock, community ban, vac ban, missing phone)
|
||||
InvalidItemType = 104, // the type of thing we were requested to act on is invalid
|
||||
IPBanned = 105, // the ip address has been banned from taking this action
|
||||
};
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Facepunch.Steamworks.Callbacks.Networking
|
||||
{
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||
internal class P2PSessionRequest
|
||||
{
|
||||
public ulong SteamID;
|
||||
|
||||
public const int CallbackId = Index.Networking + 2;
|
||||
};
|
||||
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||
internal class P2PSessionConnectFail
|
||||
{
|
||||
public ulong SteamID;
|
||||
public Steamworks.Networking.SessionError Error;
|
||||
|
||||
public const int CallbackId = Index.Networking + 3;
|
||||
};
|
||||
|
||||
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Facepunch.Steamworks.Callbacks.User
|
||||
{
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
||||
internal struct ValidateAuthTicketResponse
|
||||
{
|
||||
public ulong SteamID;
|
||||
public int AuthResponse;
|
||||
public ulong OwnerSteamID;
|
||||
|
||||
public const int CallbackId = Index.User + 43;
|
||||
|
||||
public enum Response : int
|
||||
{
|
||||
Okay = 0, // Steam has verified the user is online, the ticket is valid and ticket has not been reused.
|
||||
UserNotConnectedToSteam = 1, // The user in question is not connected to steam
|
||||
NoLicenseOrExpired = 2, // The license has expired.
|
||||
VACBanned = 3, // The user is VAC banned for this game.
|
||||
LoggedInElseWhere = 4, // The user account has logged in elsewhere and the session containing the game instance has been disconnected.
|
||||
VACCheckTimedOut = 5, // VAC has been unable to perform anti-cheat checks on this user
|
||||
AuthTicketCanceled = 6, // The ticket has been canceled by the issuer
|
||||
AuthTicketInvalidAlreadyUsed = 7, // This ticket has already been used, it is not valid.
|
||||
AuthTicketInvalid = 8, // This ticket is not from a user instance currently connected to steam.
|
||||
PublisherIssuedBan = 9, // The user is banned for this game. The ban came via the web api and not VAC
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Facepunch.Steamworks.Interop;
|
||||
|
||||
namespace Facepunch.Steamworks.Callbacks.Workshop
|
||||
{
|
||||
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
|
||||
internal struct ItemInstalled
|
||||
{
|
||||
public uint AppId;
|
||||
public ulong FileId;
|
||||
|
||||
public const int CallbackId = Index.UGC + 5;
|
||||
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
|
||||
internal struct Small
|
||||
{
|
||||
public uint AppId;
|
||||
public ulong FileId;
|
||||
};
|
||||
};
|
||||
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
|
||||
internal struct DownloadResult
|
||||
{
|
||||
public uint AppId;
|
||||
public ulong FileId;
|
||||
public Result Result;
|
||||
|
||||
public const int CallbackId = Index.UGC + 6;
|
||||
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
|
||||
internal struct Small
|
||||
{
|
||||
public uint AppId;
|
||||
public ulong FileId;
|
||||
public Result Result;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
internal class QueryCompleted : CallResult<QueryCompleted.Data, QueryCompleted.Data.Small>
|
||||
{
|
||||
public override int CallbackId { get { return Index.UGC + 1; } }
|
||||
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
|
||||
internal struct Data
|
||||
{
|
||||
internal ulong Handle;
|
||||
internal int Result;
|
||||
internal uint NumResultsReturned;
|
||||
internal uint TotalMatchingResults;
|
||||
internal bool CachedData;
|
||||
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
|
||||
internal struct Small
|
||||
{
|
||||
internal ulong Handle;
|
||||
internal int Result;
|
||||
internal uint NumResultsReturned;
|
||||
internal uint TotalMatchingResults;
|
||||
internal bool CachedData;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
internal class CreateItem : CallResult<CreateItem.Data, CreateItem.Data.Small>
|
||||
{
|
||||
public override int CallbackId { get { return Index.UGC + 3; } }
|
||||
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
|
||||
internal struct Data
|
||||
{
|
||||
internal Result Result;
|
||||
internal ulong FileId;
|
||||
internal bool NeedsLegalAgreement;
|
||||
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
|
||||
internal struct Small
|
||||
{
|
||||
internal Result Result;
|
||||
internal ulong FileId;
|
||||
|
||||
internal bool NeedsLegalAgreement;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
internal class SubmitItemUpdate : CallResult<SubmitItemUpdate.Data, SubmitItemUpdate.Data.Small>
|
||||
{
|
||||
public override int CallbackId { get { return Index.UGC + 4; } }
|
||||
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 8 )]
|
||||
internal struct Data
|
||||
{
|
||||
internal Result Result;
|
||||
internal bool NeedsLegalAgreement;
|
||||
|
||||
[StructLayout( LayoutKind.Sequential, Pack = 4 )]
|
||||
internal struct Small
|
||||
{
|
||||
internal Result Result;
|
||||
internal bool NeedsLegalAgreement;
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
30
Facepunch.Steamworks/Classes/AuthTicket.cs
Normal file
30
Facepunch.Steamworks/Classes/AuthTicket.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
public class AuthTicket : IDisposable
|
||||
{
|
||||
public byte[] Data;
|
||||
public uint Handle;
|
||||
|
||||
/// <summary>
|
||||
/// Cancels a ticket.
|
||||
/// You should cancel your ticket when you close the game or leave a server.
|
||||
/// </summary>
|
||||
public void Cancel()
|
||||
{
|
||||
if ( Handle != 0 )
|
||||
{
|
||||
SteamUser.Internal.CancelAuthTicket( Handle );
|
||||
}
|
||||
|
||||
Handle = 0;
|
||||
Data = null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Cancel();
|
||||
}
|
||||
}
|
||||
}
|
334
Facepunch.Steamworks/Classes/Dispatch.cs
Normal file
334
Facepunch.Steamworks/Classes/Dispatch.cs
Normal file
@ -0,0 +1,334 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Steamworks.Data;
|
||||
using Steamworks;
|
||||
using System.Linq;
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
/// <summary>
|
||||
/// Responsible for all callback/callresult handling
|
||||
///
|
||||
/// This manually pumps Steam's message queue and dispatches those
|
||||
/// events to any waiting callbacks/callresults.
|
||||
/// </summary>
|
||||
public static class Dispatch
|
||||
{
|
||||
/// <summary>
|
||||
/// If set then we'll call this function every time a callback is generated.
|
||||
///
|
||||
/// This is SLOW!! - it's for debugging - don't keep it on all the time. If you want to access a specific
|
||||
/// callback then please create an issue on github and I'll add it!
|
||||
///
|
||||
/// Params are : [Callback Type] [Callback Contents] [server]
|
||||
///
|
||||
/// </summary>
|
||||
public static Action<CallbackType, string, bool> OnDebugCallback;
|
||||
|
||||
/// <summary>
|
||||
/// Called if an exception happens during a callback/callresult.
|
||||
/// This is needed because the exception isn't always accessible when running
|
||||
/// async.. and can fail silently. With this hooked you won't be stuck wondering
|
||||
/// what happened.
|
||||
/// </summary>
|
||||
public static Action<Exception> OnException;
|
||||
|
||||
#region interop
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_Init", CallingConvention = CallingConvention.Cdecl )]
|
||||
internal static extern void SteamAPI_ManualDispatch_Init();
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_RunFrame", CallingConvention = CallingConvention.Cdecl )]
|
||||
internal static extern void SteamAPI_ManualDispatch_RunFrame( HSteamPipe pipe );
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_GetNextCallback", CallingConvention = CallingConvention.Cdecl )]
|
||||
[return: MarshalAs( UnmanagedType.I1 )]
|
||||
internal static extern bool SteamAPI_ManualDispatch_GetNextCallback( HSteamPipe pipe, [In, Out] ref CallbackMsg_t msg );
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_ManualDispatch_FreeLastCallback", CallingConvention = CallingConvention.Cdecl )]
|
||||
[return: MarshalAs( UnmanagedType.I1 )]
|
||||
internal static extern bool SteamAPI_ManualDispatch_FreeLastCallback( HSteamPipe pipe );
|
||||
|
||||
[StructLayout( LayoutKind.Sequential, Pack = Platform.StructPlatformPackSize )]
|
||||
internal struct CallbackMsg_t
|
||||
{
|
||||
public HSteamUser m_hSteamUser; // Specific user to whom this callback applies.
|
||||
public CallbackType Type; // Callback identifier. (Corresponds to the k_iCallback enum in the callback structure.)
|
||||
public IntPtr Data; // Points to the callback structure
|
||||
public int DataSize; // Size of the data pointed to by m_pubParam
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
internal static HSteamPipe ClientPipe { get; set; }
|
||||
internal static HSteamPipe ServerPipe { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This gets called from Client/Server Init
|
||||
/// It's important to switch to the manual dispatcher
|
||||
/// </summary>
|
||||
internal static void Init()
|
||||
{
|
||||
SteamAPI_ManualDispatch_Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure we don't call Frame in a callback - because that'll cause some issues for everyone.
|
||||
/// </summary>
|
||||
static bool runningFrame = false;
|
||||
|
||||
/// <summary>
|
||||
/// Calls RunFrame and processes events from this Steam Pipe
|
||||
/// </summary>
|
||||
internal static void Frame( HSteamPipe pipe )
|
||||
{
|
||||
if ( runningFrame )
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
runningFrame = true;
|
||||
|
||||
SteamAPI_ManualDispatch_RunFrame( pipe );
|
||||
SteamNetworkingUtils.OutputDebugMessages();
|
||||
|
||||
CallbackMsg_t msg = default;
|
||||
|
||||
while ( SteamAPI_ManualDispatch_GetNextCallback( pipe, ref msg ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
ProcessCallback( msg, pipe == ServerPipe );
|
||||
}
|
||||
finally
|
||||
{
|
||||
SteamAPI_ManualDispatch_FreeLastCallback( pipe );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( System.Exception e )
|
||||
{
|
||||
OnException?.Invoke( e );
|
||||
}
|
||||
finally
|
||||
{
|
||||
runningFrame = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To be safe we don't call the continuation functions while iterating
|
||||
/// the Callback list. This is maybe overly safe because the only way this
|
||||
/// could be an issue is if the callback list is modified in the continuation
|
||||
/// which would only happen if starting or shutting down in the callback.
|
||||
/// </summary>
|
||||
static List<Action<IntPtr>> actionsToCall = new List<Action<IntPtr>>();
|
||||
|
||||
/// <summary>
|
||||
/// A callback is a general global message
|
||||
/// </summary>
|
||||
private static void ProcessCallback( CallbackMsg_t msg, bool isServer )
|
||||
{
|
||||
OnDebugCallback?.Invoke( msg.Type, CallbackToString( msg.Type, msg.Data, msg.DataSize ), isServer );
|
||||
|
||||
// Is this a special callback telling us that the call result is ready?
|
||||
if ( msg.Type == CallbackType.SteamAPICallCompleted )
|
||||
{
|
||||
ProcessResult( msg );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Callbacks.TryGetValue( msg.Type, out var list ) )
|
||||
{
|
||||
actionsToCall.Clear();
|
||||
|
||||
foreach ( var item in list )
|
||||
{
|
||||
if ( item.server != isServer )
|
||||
continue;
|
||||
|
||||
actionsToCall.Add( item.action );
|
||||
}
|
||||
|
||||
foreach ( var action in actionsToCall )
|
||||
{
|
||||
action( msg.Data );
|
||||
}
|
||||
|
||||
actionsToCall.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a callback, try to turn it into a string
|
||||
/// </summary>
|
||||
internal static string CallbackToString( CallbackType type, IntPtr data, int expectedsize )
|
||||
{
|
||||
if ( !CallbackTypeFactory.All.TryGetValue( type, out var t ) )
|
||||
return $"[{type} not in sdk]";
|
||||
|
||||
var strct = data.ToType( t );
|
||||
if ( strct == null )
|
||||
return "[null]";
|
||||
|
||||
var str = "";
|
||||
|
||||
var fields = t.GetFields( System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic );
|
||||
|
||||
if ( fields.Length == 0 )
|
||||
return "[no fields]";
|
||||
|
||||
var columnSize = fields.Max( x => x.Name.Length ) + 1;
|
||||
|
||||
if ( columnSize < 10 )
|
||||
columnSize = 10;
|
||||
|
||||
foreach ( var field in fields )
|
||||
{
|
||||
var spaces = (columnSize - field.Name.Length);
|
||||
if ( spaces < 0 ) spaces = 0;
|
||||
|
||||
str += $"{new String( ' ', spaces )}{field.Name}: {field.GetValue( strct )}\n";
|
||||
}
|
||||
|
||||
return str.Trim( '\n' );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A result is a reply to a specific command
|
||||
/// </summary>
|
||||
private static void ProcessResult( CallbackMsg_t msg )
|
||||
{
|
||||
var result = msg.Data.ToType<SteamAPICallCompleted_t>();
|
||||
|
||||
//
|
||||
// Do we have an entry added via OnCallComplete
|
||||
//
|
||||
if ( !ResultCallbacks.TryGetValue( result.AsyncCall, out var callbackInfo ) )
|
||||
{
|
||||
//
|
||||
// This can happen if the callback result was immediately available
|
||||
// so we just returned that without actually going through the callback
|
||||
// dance. It's okay for this to fail.
|
||||
//
|
||||
|
||||
//
|
||||
// But still let everyone know that this happened..
|
||||
//
|
||||
OnDebugCallback?.Invoke( (CallbackType)result.Callback, $"[no callback waiting/required]", false );
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove it before we do anything, incase the continuation throws exceptions
|
||||
ResultCallbacks.Remove( result.AsyncCall );
|
||||
|
||||
// At this point whatever async routine called this
|
||||
// continues running.
|
||||
callbackInfo.continuation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pumps the queue in an async loop so we don't
|
||||
/// have to think about it. This has the advantage that
|
||||
/// you can call .Wait() on async shit and it still works.
|
||||
/// </summary>
|
||||
internal static async void LoopClientAsync()
|
||||
{
|
||||
while ( ClientPipe != 0 )
|
||||
{
|
||||
Frame( ClientPipe );
|
||||
await Task.Delay( 16 );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pumps the queue in an async loop so we don't
|
||||
/// have to think about it. This has the advantage that
|
||||
/// you can call .Wait() on async shit and it still works.
|
||||
/// </summary>
|
||||
internal static async void LoopServerAsync()
|
||||
{
|
||||
while ( ServerPipe != 0 )
|
||||
{
|
||||
Frame( ServerPipe );
|
||||
await Task.Delay( 32 );
|
||||
}
|
||||
}
|
||||
|
||||
struct ResultCallback
|
||||
{
|
||||
public Action continuation;
|
||||
public bool server;
|
||||
}
|
||||
|
||||
static Dictionary<ulong, ResultCallback> ResultCallbacks = new Dictionary<ulong, ResultCallback>();
|
||||
|
||||
/// <summary>
|
||||
/// Watch for a steam api call
|
||||
/// </summary>
|
||||
internal static void OnCallComplete<T>( SteamAPICall_t call, Action continuation, bool server ) where T : struct, ICallbackData
|
||||
{
|
||||
ResultCallbacks[call.Value] = new ResultCallback
|
||||
{
|
||||
continuation = continuation,
|
||||
server = server
|
||||
};
|
||||
}
|
||||
|
||||
struct Callback
|
||||
{
|
||||
public Action<IntPtr> action;
|
||||
public bool server;
|
||||
}
|
||||
|
||||
static Dictionary<CallbackType, List<Callback>> Callbacks = new Dictionary<CallbackType, List<Callback>>();
|
||||
|
||||
/// <summary>
|
||||
/// Install a global callback. The passed function will get called if it's all good.
|
||||
/// </summary>
|
||||
internal static void Install<T>( Action<T> p, bool server = false ) where T : ICallbackData
|
||||
{
|
||||
var t = default( T );
|
||||
var type = t.CallbackType;
|
||||
|
||||
if ( !Callbacks.TryGetValue( type, out var list ) )
|
||||
{
|
||||
list = new List<Callback>();
|
||||
Callbacks[type] = list;
|
||||
}
|
||||
|
||||
list.Add( new Callback
|
||||
{
|
||||
action = x => p( x.ToType<T>() ),
|
||||
server = server
|
||||
} );
|
||||
}
|
||||
|
||||
internal static void ShutdownServer()
|
||||
{
|
||||
ServerPipe = 0;
|
||||
|
||||
foreach ( var callback in Callbacks )
|
||||
{
|
||||
Callbacks[callback.Key].RemoveAll( x => x.server );
|
||||
}
|
||||
|
||||
ResultCallbacks = ResultCallbacks.Where( x => !x.Value.server )
|
||||
.ToDictionary( x => x.Key, x => x.Value );
|
||||
}
|
||||
|
||||
internal static void ShutdownClient()
|
||||
{
|
||||
ClientPipe = 0;
|
||||
|
||||
foreach ( var callback in Callbacks )
|
||||
{
|
||||
Callbacks[callback.Key].RemoveAll( x => !x.server );
|
||||
}
|
||||
|
||||
ResultCallbacks = ResultCallbacks.Where( x => x.Value.server )
|
||||
.ToDictionary( x => x.Key, x => x.Value );
|
||||
}
|
||||
}
|
||||
}
|
54
Facepunch.Steamworks/Classes/SteamApi.cs
Normal file
54
Facepunch.Steamworks/Classes/SteamApi.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Steamworks.Data;
|
||||
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
internal static class SteamAPI
|
||||
{
|
||||
internal static class Native
|
||||
{
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamInternal_SteamAPI_Init", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern SteamAPIInitResult SteamInternal_SteamAPI_Init( IntPtr pszInternalCheckInterfaceVersions, IntPtr pOutErrMsg );
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_Shutdown", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern void SteamAPI_Shutdown();
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_GetHSteamPipe", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern HSteamPipe SteamAPI_GetHSteamPipe();
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamAPI_RestartAppIfNecessary", CallingConvention = CallingConvention.Cdecl )]
|
||||
[return: MarshalAs( UnmanagedType.I1 )]
|
||||
public static extern bool SteamAPI_RestartAppIfNecessary( uint unOwnAppID );
|
||||
|
||||
}
|
||||
|
||||
static internal SteamAPIInitResult Init( string pszInternalCheckInterfaceVersions, out string pOutErrMsg )
|
||||
{
|
||||
using var interfaceVersionsStr = new Utf8StringToNative( pszInternalCheckInterfaceVersions );
|
||||
using var buffer = Helpers.Memory.Take();
|
||||
var result = Native.SteamInternal_SteamAPI_Init( interfaceVersionsStr.Pointer, buffer.Ptr );
|
||||
pOutErrMsg = Helpers.MemoryToString( buffer.Ptr );
|
||||
return result;
|
||||
}
|
||||
|
||||
static internal void Shutdown()
|
||||
{
|
||||
Native.SteamAPI_Shutdown();
|
||||
}
|
||||
|
||||
static internal HSteamPipe GetHSteamPipe()
|
||||
{
|
||||
return Native.SteamAPI_GetHSteamPipe();
|
||||
}
|
||||
|
||||
static internal bool RestartAppIfNecessary( uint unOwnAppID )
|
||||
{
|
||||
return Native.SteamAPI_RestartAppIfNecessary( unOwnAppID );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
40
Facepunch.Steamworks/Classes/SteamGameServer.cs
Normal file
40
Facepunch.Steamworks/Classes/SteamGameServer.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Steamworks.Data;
|
||||
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
internal static class SteamGameServer
|
||||
{
|
||||
internal static class Native
|
||||
{
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamGameServer_RunCallbacks", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern void SteamGameServer_RunCallbacks();
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamGameServer_Shutdown", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern void SteamGameServer_Shutdown();
|
||||
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamGameServer_GetHSteamPipe", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern HSteamPipe SteamGameServer_GetHSteamPipe();
|
||||
|
||||
}
|
||||
static internal void RunCallbacks()
|
||||
{
|
||||
Native.SteamGameServer_RunCallbacks();
|
||||
}
|
||||
|
||||
static internal void Shutdown()
|
||||
{
|
||||
Native.SteamGameServer_Shutdown();
|
||||
}
|
||||
|
||||
static internal HSteamPipe GetHSteamPipe()
|
||||
{
|
||||
return Native.SteamGameServer_GetHSteamPipe();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
28
Facepunch.Steamworks/Classes/SteamInternal.cs
Normal file
28
Facepunch.Steamworks/Classes/SteamInternal.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Steamworks.Data;
|
||||
|
||||
|
||||
namespace Steamworks
|
||||
{
|
||||
internal static class SteamInternal
|
||||
{
|
||||
internal static class Native
|
||||
{
|
||||
[DllImport( Platform.LibraryName, EntryPoint = "SteamInternal_GameServer_Init_V2", CallingConvention = CallingConvention.Cdecl )]
|
||||
public static extern SteamAPIInitResult SteamInternal_GameServer_Init_V2( uint unIP, ushort usGamePort, ushort usQueryPort, int eServerMode, IntPtr pchVersionString, IntPtr pszInternalCheckInterfaceVersions, IntPtr pOutErrMsg );
|
||||
}
|
||||
|
||||
static internal SteamAPIInitResult GameServer_Init( uint unIP, ushort usGamePort, ushort usQueryPort, int eServerMode, string pchVersionString, string pszInternalCheckInterfaceVersions, out string pOutErrMsg )
|
||||
{
|
||||
using var versionStr = new Utf8StringToNative( pchVersionString );
|
||||
using var interfaceVersionsStr = new Utf8StringToNative( pszInternalCheckInterfaceVersions );
|
||||
using var buffer = Helpers.Memory.Take();
|
||||
var result = Native.SteamInternal_GameServer_Init_V2( unIP, usGamePort, usQueryPort, eServerMode, versionStr.Pointer, interfaceVersionsStr.Pointer, buffer.Ptr );
|
||||
pOutErrMsg = Helpers.MemoryToString( buffer.Ptr );
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public partial class Client : BaseSteamworks
|
||||
{
|
||||
/// <summary>
|
||||
/// Current user's Username
|
||||
/// </summary>
|
||||
public string Username { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current user's SteamId
|
||||
/// </summary>
|
||||
public ulong SteamId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current Beta name, if ser
|
||||
/// </summary>
|
||||
public string BetaName { get; private set; }
|
||||
|
||||
public Voice Voice { get; internal set; }
|
||||
|
||||
public Client( uint appId )
|
||||
{
|
||||
Valve.Steamworks.SteamAPIInterop.SteamAPI_Init();
|
||||
|
||||
native = new Interop.NativeInterface();
|
||||
|
||||
//
|
||||
// Get other interfaces
|
||||
//
|
||||
if ( !native.InitClient() )
|
||||
{
|
||||
native.Dispose();
|
||||
native = null;
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Set up warning hook callback
|
||||
//
|
||||
SteamAPIWarningMessageHook ptr = InternalOnWarning;
|
||||
native.client.SetWarningMessageHook( Marshal.GetFunctionPointerForDelegate( ptr ) );
|
||||
|
||||
//
|
||||
// Setup interfaces that client and server both have
|
||||
//
|
||||
SetupCommonInterfaces();
|
||||
|
||||
//
|
||||
// Client only interfaces
|
||||
//
|
||||
Voice = new Voice( this );
|
||||
|
||||
|
||||
//
|
||||
// Cache common, unchanging info
|
||||
//
|
||||
AppId = appId;
|
||||
Username = native.friends.GetPersonaName();
|
||||
SteamId = native.user.GetSteamID();
|
||||
BetaName = native.apps.GetCurrentBetaName();
|
||||
|
||||
//
|
||||
// Run update, first call does some initialization
|
||||
//
|
||||
Update();
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer( CallingConvention.Cdecl )]
|
||||
public delegate void SteamAPIWarningMessageHook( int nSeverity, System.Text.StringBuilder pchDebugText );
|
||||
|
||||
private void InternalOnWarning( int nSeverity, System.Text.StringBuilder text )
|
||||
{
|
||||
if ( OnMessage != null )
|
||||
{
|
||||
OnMessage( ( MessageType)nSeverity, text.ToString() );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Should be called at least once every frame
|
||||
/// </summary>
|
||||
public override void Update()
|
||||
{
|
||||
if ( !IsValid )
|
||||
return;
|
||||
|
||||
Valve.Steamworks.SteamAPI.RunCallbacks();
|
||||
|
||||
Voice.Update();
|
||||
|
||||
base.Update();
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if ( Voice != null )
|
||||
{
|
||||
Voice.Dispose();
|
||||
Voice = null;
|
||||
}
|
||||
|
||||
base.Dispose();
|
||||
|
||||
Valve.Interop.NativeEntrypoints.Extended.SteamAPI_Shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public partial class Client : IDisposable
|
||||
{
|
||||
App _app;
|
||||
|
||||
public App App
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _app == null )
|
||||
_app = new App( this );
|
||||
|
||||
return _app;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class App
|
||||
{
|
||||
internal Client client;
|
||||
|
||||
internal App( Client c )
|
||||
{
|
||||
client = c;
|
||||
}
|
||||
|
||||
public void MarkContentCorrupt( bool missingFilesOnly = false )
|
||||
{
|
||||
client.native.apps.MarkContentCorrupt( missingFilesOnly );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current BuildId of the game.
|
||||
/// This is pretty useless, as it isn't guarenteed to return
|
||||
/// the build id you're playing, or the latest build id.
|
||||
/// </summary>
|
||||
public int BuildId
|
||||
{
|
||||
get
|
||||
{
|
||||
return client.native.apps.GetAppBuildId();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public partial class Client : IDisposable
|
||||
{
|
||||
Auth _auth;
|
||||
|
||||
public Auth Auth
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _auth == null )
|
||||
_auth = new Auth{ client = this };
|
||||
|
||||
return _auth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Auth
|
||||
{
|
||||
internal Client client;
|
||||
|
||||
public class Ticket : IDisposable
|
||||
{
|
||||
internal Client client;
|
||||
|
||||
public byte[] Data;
|
||||
public uint Handle;
|
||||
|
||||
/// <summary>
|
||||
/// Cancels a ticket.
|
||||
/// You should cancel your ticket when you close the game or leave a server.
|
||||
/// </summary>
|
||||
public void Cancel()
|
||||
{
|
||||
if ( client.IsValid && Handle != 0 )
|
||||
{
|
||||
client.native.user.CancelAuthTicket( Handle );
|
||||
Handle = 0;
|
||||
Data = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an auth ticket.
|
||||
/// Which you can send to a server to authenticate that you are who you say you are.
|
||||
/// </summary>
|
||||
public unsafe Ticket GetAuthSessionTicket()
|
||||
{
|
||||
var data = new byte[1024];
|
||||
|
||||
fixed ( byte* b = data )
|
||||
{
|
||||
uint ticketLength = 0;
|
||||
uint ticket = client.native.user.GetAuthSessionTicket( (IntPtr) b, data.Length, ref ticketLength );
|
||||
|
||||
if ( ticket == 0 )
|
||||
return null;
|
||||
|
||||
return new Ticket()
|
||||
{
|
||||
client = client,
|
||||
Data = data.Take( (int)ticketLength ).ToArray(),
|
||||
Handle = ticket
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,248 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Valve.Steamworks;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public partial class Client : IDisposable
|
||||
{
|
||||
Friends _friends;
|
||||
|
||||
public Friends Friends
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _friends == null )
|
||||
_friends = new Friends( this );
|
||||
|
||||
return _friends;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SteamFriend
|
||||
{
|
||||
/// <summary>
|
||||
/// Steam Id
|
||||
/// </summary>
|
||||
public ulong Id { get; internal set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Return true if blocked
|
||||
/// </summary>
|
||||
public bool IsBlocked { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if is a friend. Returns false if blocked, request etc.
|
||||
/// </summary>
|
||||
public bool IsFriend { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Their current display name
|
||||
/// </summary>
|
||||
public string Name;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this friend is online
|
||||
/// </summary>
|
||||
public bool IsOnline { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this friend is online and playing this game
|
||||
/// </summary>
|
||||
public bool IsPlayingThisGame { get { return CurrentAppId == Client.AppId; } }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this friend is online and playing this game
|
||||
/// </summary>
|
||||
public bool IsPlaying { get { return CurrentAppId != 0; } }
|
||||
|
||||
/// <summary>
|
||||
/// The AppId this guy is playing
|
||||
/// </summary>
|
||||
public ulong CurrentAppId { get; internal set; }
|
||||
|
||||
public uint ServerIp { get; internal set; }
|
||||
public int ServerGamePort { get; internal set; }
|
||||
public int ServerQueryPort { get; internal set; }
|
||||
public ulong ServerLobbyId { get; internal set; }
|
||||
|
||||
internal Client Client { get; set; }
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
Name = Client.native.friends.GetFriendPersonaName( Id );
|
||||
|
||||
EFriendRelationship relationship = (EFriendRelationship) Client.native.friends.GetFriendRelationship( Id );
|
||||
|
||||
IsBlocked = relationship == EFriendRelationship.k_EFriendRelationshipBlocked;
|
||||
IsFriend = relationship == EFriendRelationship.k_EFriendRelationshipFriend;
|
||||
|
||||
CurrentAppId = 0;
|
||||
ServerIp = 0;
|
||||
ServerGamePort = 0;
|
||||
ServerQueryPort = 0;
|
||||
ServerLobbyId = 0;
|
||||
|
||||
FriendGameInfo_t gameInfo = new FriendGameInfo_t();
|
||||
if ( Client.native.friends.GetFriendGamePlayed( Id, out gameInfo ) && gameInfo.m_gameID > 0 )
|
||||
{
|
||||
CurrentAppId = gameInfo.m_gameID;
|
||||
ServerIp = gameInfo.m_unGameIP;
|
||||
ServerGamePort = gameInfo.m_usGamePort;
|
||||
ServerQueryPort = gameInfo.m_usQueryPort;
|
||||
ServerLobbyId = gameInfo.m_steamIDLobby;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Friends
|
||||
{
|
||||
internal Client client;
|
||||
|
||||
internal Friends( Client c )
|
||||
{
|
||||
client = c;
|
||||
}
|
||||
|
||||
public string GetName( ulong steamid )
|
||||
{
|
||||
client.native.friends.RequestUserInformation( steamid, true );
|
||||
|
||||
return client.native.friends.GetFriendPersonaName( steamid );
|
||||
}
|
||||
|
||||
private List<SteamFriend> _allFriends;
|
||||
|
||||
/// <summary>
|
||||
/// Returns all friends, even blocked, ignored, friend requests etc
|
||||
/// </summary>
|
||||
public IEnumerable<SteamFriend> All
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _allFriends == null )
|
||||
{
|
||||
_allFriends = new List<SteamFriend>();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
return _allFriends;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<SteamFriend> AllFriends
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach ( var friend in All )
|
||||
{
|
||||
if ( !friend.IsFriend ) continue;
|
||||
|
||||
yield return friend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<SteamFriend> AllBlocked
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach ( var friend in All )
|
||||
{
|
||||
if ( !friend.IsBlocked ) continue;
|
||||
|
||||
yield return friend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
if ( _allFriends == null )
|
||||
{
|
||||
_allFriends = new List<SteamFriend>();
|
||||
}
|
||||
|
||||
_allFriends.Clear();
|
||||
|
||||
var flags = (int) EFriendFlags.k_EFriendFlagAll;
|
||||
var count = client.native.friends.GetFriendCount( flags );
|
||||
|
||||
for ( int i=0; i<count; i++ )
|
||||
{
|
||||
var steamid = client.native.friends.GetFriendByIndex( i, flags );
|
||||
_allFriends.Add( Get( steamid ) );
|
||||
}
|
||||
}
|
||||
|
||||
public enum AvatarSize
|
||||
{
|
||||
/// <summary>
|
||||
/// Should be 32x32 - but make sure to check!
|
||||
/// </summary>
|
||||
Small,
|
||||
|
||||
/// <summary>
|
||||
/// Should be 64x64 - but make sure to check!
|
||||
/// </summary>
|
||||
Medium,
|
||||
|
||||
/// <summary>
|
||||
/// Should be 184x184 - but make sure to check!
|
||||
/// </summary>
|
||||
Large
|
||||
}
|
||||
|
||||
public Image GetAvatar( AvatarSize size, ulong steamid )
|
||||
{
|
||||
var imageid = 0;
|
||||
|
||||
switch ( size )
|
||||
{
|
||||
case AvatarSize.Small:
|
||||
imageid = client.native.friends.GetSmallFriendAvatar( steamid );
|
||||
break;
|
||||
case AvatarSize.Medium:
|
||||
imageid = client.native.friends.GetMediumFriendAvatar( steamid );
|
||||
break;
|
||||
case AvatarSize.Large:
|
||||
imageid = client.native.friends.GetLargeFriendAvatar( steamid );
|
||||
break;
|
||||
}
|
||||
|
||||
var img = new Image()
|
||||
{
|
||||
Id = imageid
|
||||
};
|
||||
|
||||
if ( imageid == 0 )
|
||||
return img;
|
||||
|
||||
if ( img.TryLoad( client.native.utils ) )
|
||||
return img;
|
||||
|
||||
throw new System.NotImplementedException( "Deferred Avatar Loading Todo" );
|
||||
// Add to image loading list
|
||||
|
||||
//return img;
|
||||
}
|
||||
|
||||
|
||||
public SteamFriend Get( ulong steamid )
|
||||
{
|
||||
var f = new SteamFriend()
|
||||
{
|
||||
Id = steamid,
|
||||
Client = client
|
||||
};
|
||||
|
||||
f.Refresh();
|
||||
|
||||
return f;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Valve.Steamworks;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public class Image
|
||||
{
|
||||
public int Id { get; internal set; }
|
||||
public int Width { get; internal set; }
|
||||
public int Height { get; internal set; }
|
||||
|
||||
public byte[] Data { get; internal set; }
|
||||
|
||||
public bool IsLoaded { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Return true if this image couldn't be loaded for some reason
|
||||
/// </summary>
|
||||
public bool IsError { get; internal set; }
|
||||
|
||||
unsafe internal bool TryLoad( ISteamUtils utils )
|
||||
{
|
||||
if ( IsLoaded ) return true;
|
||||
|
||||
uint width = 0, height = 0;
|
||||
|
||||
if ( utils.GetImageSize( Id, ref width, ref height ) == false )
|
||||
{
|
||||
IsError = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
var buffer = new byte[ width * height * 4 ];
|
||||
|
||||
fixed ( byte* ptr = buffer )
|
||||
{
|
||||
if ( utils.GetImageRGBA( Id, (IntPtr) ptr, buffer.Length ) == false )
|
||||
{
|
||||
IsError = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Width = (int) width;
|
||||
Height = (int) height;
|
||||
Data = buffer;
|
||||
IsLoaded = true;
|
||||
IsError = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Color GetPixel( int x, int y )
|
||||
{
|
||||
if ( !IsLoaded ) throw new System.Exception( "Image not loaded" );
|
||||
if ( x < 0 || x >= Width ) throw new System.Exception( "x out of bounds" );
|
||||
if ( y < 0 || y >= Height ) throw new System.Exception( "y out of bounds" );
|
||||
|
||||
Color c = new Color();
|
||||
|
||||
var i = ( y * Width + x ) * 4;
|
||||
|
||||
c.r = Data[i + 0];
|
||||
c.g = Data[i + 1];
|
||||
c.b = Data[i + 2];
|
||||
c.a = Data[i + 3];
|
||||
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
public struct Color
|
||||
{
|
||||
public byte r, g, b, a;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,42 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public partial class Client : IDisposable
|
||||
{
|
||||
private Overlay _overlay;
|
||||
|
||||
public Overlay Overlay
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _overlay == null )
|
||||
_overlay = new Overlay { client = this };
|
||||
|
||||
return _overlay;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Overlay
|
||||
{
|
||||
internal Client client;
|
||||
|
||||
public void OpenUserPage( string name, ulong steamid ) { client.native.friends.ActivateGameOverlayToUser( name, steamid ); }
|
||||
|
||||
public void OpenProfile( ulong steamid ) { OpenUserPage( "steamid", steamid ); }
|
||||
public void OpenChat( ulong steamid ){ OpenUserPage( "chat", steamid ); }
|
||||
public void OpenTrade( ulong steamid ) { OpenUserPage( "jointrade", steamid ); }
|
||||
public void OpenStats( ulong steamid ) { OpenUserPage( "stats", steamid ); }
|
||||
public void OpenAchievements( ulong steamid ) { OpenUserPage( "achievements", steamid ); }
|
||||
public void AddFriend( ulong steamid ) { OpenUserPage( "friendadd", steamid ); }
|
||||
public void RemoveFriend( ulong steamid ) { OpenUserPage( "friendremove", steamid ); }
|
||||
public void AcceptFriendRequest( ulong steamid ) { OpenUserPage( "friendrequestaccept", steamid ); }
|
||||
public void IgnoreFriendRequest( ulong steamid ) { OpenUserPage( "friendrequestignore", steamid ); }
|
||||
|
||||
public void OpenUrl( string url ) { client.native.friends.ActivateGameOverlayToWebPage( url ); }
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public partial class Client : IDisposable
|
||||
{
|
||||
Screenshots _screenshots;
|
||||
|
||||
public Screenshots Screenshots
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _screenshots == null )
|
||||
_screenshots = new Screenshots( this );
|
||||
|
||||
return _screenshots;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Screenshots
|
||||
{
|
||||
internal Client client;
|
||||
|
||||
internal Screenshots( Client c )
|
||||
{
|
||||
client = c;
|
||||
}
|
||||
|
||||
public void Trigger()
|
||||
{
|
||||
client.native.screenshots.TriggerScreenshot();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Valve.Steamworks;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public class Server
|
||||
{
|
||||
internal Client client;
|
||||
|
||||
internal Server( Client c )
|
||||
{
|
||||
client = c;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
public int Ping { get; set; }
|
||||
public string GameDir { get; set; }
|
||||
public string Map { get; set; }
|
||||
public string Description { get; set; }
|
||||
public uint AppId { get; set; }
|
||||
public int Players { get; set; }
|
||||
public int MaxPlayers { get; set; }
|
||||
public int BotPlayers { get; set; }
|
||||
public bool Passworded { get; set; }
|
||||
public bool Secure { get; set; }
|
||||
public uint LastTimePlayed { get; set; }
|
||||
public int Version { get; set; }
|
||||
public string[] Tags { get; set; }
|
||||
public ulong SteamId { get; set; }
|
||||
|
||||
public uint Address { get; set; }
|
||||
|
||||
public int ConnectionPort { get; set; }
|
||||
|
||||
public int QueryPort { get; set; }
|
||||
|
||||
public string AddressString
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Format( "{0}.{1}.{2}.{3}", ( Address >> 24 ) & 0xFFul, ( Address >> 16 ) & 0xFFul, ( Address >> 8 ) & 0xFFul, Address & 0xFFul );
|
||||
}
|
||||
}
|
||||
public string ConnectionAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Format( "{0}.{1}.{2}.{3}:{4}", ( Address >> 24 ) & 0xFFul, ( Address >> 16 ) & 0xFFul, ( Address >> 8 ) & 0xFFul, Address & 0xFFul, ConnectionPort );
|
||||
}
|
||||
}
|
||||
|
||||
internal static Server FromSteam( Client c, gameserveritem_t item )
|
||||
{
|
||||
return new Server( c )
|
||||
{
|
||||
Address = item.m_NetAdr.m_unIP,
|
||||
ConnectionPort = item.m_NetAdr.m_usConnectionPort,
|
||||
QueryPort = item.m_NetAdr.m_usQueryPort,
|
||||
Name = item.m_szServerName,
|
||||
Ping = item.m_nPing,
|
||||
GameDir = item.m_szGameDir,
|
||||
Map = item.m_szMap,
|
||||
Description = item.m_szGameDescription,
|
||||
AppId = item.m_nAppID,
|
||||
Players = item.m_nPlayers,
|
||||
MaxPlayers = item.m_nMaxPlayers,
|
||||
BotPlayers = item.m_nBotPlayers,
|
||||
Passworded = item.m_bPassword,
|
||||
Secure = item.m_bSecure,
|
||||
LastTimePlayed = item.m_ulTimeLastPlayed,
|
||||
Version = item.m_nServerVersion,
|
||||
Tags = item.m_szGameTags == null ? null : item.m_szGameTags.Split( ',' ),
|
||||
SteamId = item.m_steamID
|
||||
};
|
||||
}
|
||||
|
||||
public Dictionary<string, string> Rules;
|
||||
public Action OnServerRules;
|
||||
|
||||
public void UpdateRules()
|
||||
{
|
||||
|
||||
//
|
||||
//
|
||||
// TEMPORARY, WE NEED TO WRITE OUR OWN VERSION OF THIS, DOESN'T WORK ON SPLIT PACKETS ETC
|
||||
//
|
||||
//
|
||||
|
||||
using ( var q = new SourceServerQuery( AddressString, ConnectionPort ) )
|
||||
{
|
||||
Rules = q.GetRules();
|
||||
}
|
||||
|
||||
if ( OnServerRules != null && Rules != null )
|
||||
OnServerRules();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,215 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Valve.Steamworks;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public partial class ServerList
|
||||
{
|
||||
public class Request : IDisposable
|
||||
{
|
||||
internal Client client;
|
||||
|
||||
internal List<SubRequest> Requests = new List<SubRequest>();
|
||||
|
||||
internal class SubRequest
|
||||
{
|
||||
internal IntPtr Request;
|
||||
internal int Pointer = 0;
|
||||
internal List<int> WatchList = new List<int>();
|
||||
|
||||
internal bool Update( ISteamMatchmakingServers servers, Action<gameserveritem_t> OnServer, Action OnUpdate )
|
||||
{
|
||||
if ( Request == IntPtr.Zero )
|
||||
return true;
|
||||
|
||||
bool changes = false;
|
||||
|
||||
//
|
||||
// Add any servers we're not watching to our watch list
|
||||
//
|
||||
var count = servers.GetServerCount( Request );
|
||||
if ( count != Pointer )
|
||||
{
|
||||
for ( int i = Pointer; i < count; i++ )
|
||||
{
|
||||
WatchList.Add( i );
|
||||
}
|
||||
}
|
||||
Pointer = count;
|
||||
|
||||
//
|
||||
// Remove any servers that respond successfully
|
||||
//
|
||||
WatchList.RemoveAll( x =>
|
||||
{
|
||||
var info = servers.GetServerDetails( Request, x );
|
||||
if ( info.m_bHadSuccessfulResponse )
|
||||
{
|
||||
OnServer( info );
|
||||
changes = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} );
|
||||
|
||||
//
|
||||
// If we've finished refreshing
|
||||
//
|
||||
if ( servers.IsRefreshing( Request ) == false )
|
||||
{
|
||||
//
|
||||
// Put any other servers on the 'no response' list
|
||||
//
|
||||
WatchList.RemoveAll( x =>
|
||||
{
|
||||
var info = servers.GetServerDetails( Request, x );
|
||||
OnServer( info );
|
||||
return true;
|
||||
} );
|
||||
|
||||
servers.CancelQuery( Request );
|
||||
Request = IntPtr.Zero;
|
||||
changes = true;
|
||||
}
|
||||
|
||||
if ( changes && OnUpdate != null )
|
||||
OnUpdate();
|
||||
|
||||
return Request == IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
public Action OnUpdate;
|
||||
|
||||
/// <summary>
|
||||
/// A list of servers that responded. If you're only interested in servers that responded since you
|
||||
/// last updated, then simply clear this list.
|
||||
/// </summary>
|
||||
public List<Server> Responded = new List<Server>();
|
||||
|
||||
/// <summary>
|
||||
/// A list of servers that were in the master list but didn't respond.
|
||||
/// </summary>
|
||||
public List<Server> Unresponsive = new List<Server>();
|
||||
|
||||
/// <summary>
|
||||
/// True when we have finished
|
||||
/// </summary>
|
||||
public bool Finished = false;
|
||||
|
||||
internal Request( Client c )
|
||||
{
|
||||
client = c;
|
||||
|
||||
client.OnUpdate += Update;
|
||||
}
|
||||
|
||||
~Request()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
internal IEnumerable<string> ServerList { get; set; }
|
||||
|
||||
|
||||
internal void StartCustomQuery()
|
||||
{
|
||||
if ( ServerList == null )
|
||||
return;
|
||||
|
||||
int blockSize = 16;
|
||||
int Pointer = 0;
|
||||
|
||||
while ( true )
|
||||
{
|
||||
var sublist = ServerList.Skip( Pointer ).Take( blockSize );
|
||||
|
||||
if ( sublist.Count() == 0 )
|
||||
break;
|
||||
|
||||
Pointer += sublist.Count();
|
||||
|
||||
var filter = new Filter();
|
||||
filter.Add( "or", sublist.Count().ToString() );
|
||||
|
||||
foreach ( var server in sublist )
|
||||
{
|
||||
filter.Add( "gameaddr", server );
|
||||
}
|
||||
|
||||
filter.Start();
|
||||
var id = client.native.servers.RequestInternetServerList( client.AppId, filter.NativeArray, filter.Count, IntPtr.Zero );
|
||||
filter.Free();
|
||||
|
||||
AddRequest( id );
|
||||
}
|
||||
|
||||
ServerList = null;
|
||||
}
|
||||
|
||||
internal void AddRequest( IntPtr id )
|
||||
{
|
||||
Requests.Add( new SubRequest() { Request = id } );
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if ( Requests.Count == 0 )
|
||||
return;
|
||||
|
||||
for( int i=0; i< Requests.Count(); i++ )
|
||||
{
|
||||
if ( Requests[i].Update( client.native.servers, OnServer, OnUpdate ) )
|
||||
{
|
||||
Requests.RemoveAt( i );
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
if ( Requests.Count == 0 )
|
||||
{
|
||||
Finished = true;
|
||||
client.OnUpdate -= Update;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnServer( gameserveritem_t info )
|
||||
{
|
||||
if ( info.m_bHadSuccessfulResponse )
|
||||
{
|
||||
Responded.Add( Server.FromSteam( client, info ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
Unresponsive.Add( Server.FromSteam( client, info ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposing will end the query
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
client.OnUpdate -= Update;
|
||||
|
||||
//
|
||||
// Cancel the query if it's still running
|
||||
//
|
||||
foreach( var subRequest in Requests )
|
||||
{
|
||||
if ( client.IsValid )
|
||||
client.native.servers.CancelQuery( subRequest.Request );
|
||||
}
|
||||
Requests.Clear();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Valve.Steamworks;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public partial class ServerList
|
||||
{
|
||||
public class Server
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Ping { get; set; }
|
||||
public string GameDir { get; set; }
|
||||
public string Map { get; set; }
|
||||
public string Description { get; set; }
|
||||
public uint AppId { get; set; }
|
||||
public int Players { get; set; }
|
||||
public int MaxPlayers { get; set; }
|
||||
public int BotPlayers { get; set; }
|
||||
public bool Passworded { get; set; }
|
||||
public bool Secure { get; set; }
|
||||
public uint LastTimePlayed { get; set; }
|
||||
public int Version { get; set; }
|
||||
public string[] Tags { get; set; }
|
||||
public ulong SteamId { get; set; }
|
||||
public uint Address { get; set; }
|
||||
public int ConnectionPort { get; set; }
|
||||
public int QueryPort { get; set; }
|
||||
|
||||
internal Client Client;
|
||||
|
||||
public string AddressString
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Format( "{0}.{1}.{2}.{3}", ( Address >> 24 ) & 0xFFul, ( Address >> 16 ) & 0xFFul, ( Address >> 8 ) & 0xFFul, Address & 0xFFul );
|
||||
}
|
||||
}
|
||||
public string ConnectionAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Format( "{0}.{1}.{2}.{3}:{4}", ( Address >> 24 ) & 0xFFul, ( Address >> 16 ) & 0xFFul, ( Address >> 8 ) & 0xFFul, Address & 0xFFul, ConnectionPort );
|
||||
}
|
||||
}
|
||||
|
||||
internal static Server FromSteam( Client client, gameserveritem_t item )
|
||||
{
|
||||
return new Server()
|
||||
{
|
||||
Client = client,
|
||||
Address = item.m_NetAdr.m_unIP,
|
||||
ConnectionPort = item.m_NetAdr.m_usConnectionPort,
|
||||
QueryPort = item.m_NetAdr.m_usQueryPort,
|
||||
Name = item.m_szServerName,
|
||||
Ping = item.m_nPing,
|
||||
GameDir = item.m_szGameDir,
|
||||
Map = item.m_szMap,
|
||||
Description = item.m_szGameDescription,
|
||||
AppId = item.m_nAppID,
|
||||
Players = item.m_nPlayers,
|
||||
MaxPlayers = item.m_nMaxPlayers,
|
||||
BotPlayers = item.m_nBotPlayers,
|
||||
Passworded = item.m_bPassword,
|
||||
Secure = item.m_bSecure,
|
||||
LastTimePlayed = item.m_ulTimeLastPlayed,
|
||||
Version = item.m_nServerVersion,
|
||||
Tags = item.m_szGameTags == null ? null : item.m_szGameTags.Split( ',' ),
|
||||
SteamId = item.m_steamID
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback when rules are receieved.
|
||||
/// The bool is true if server responded properly.
|
||||
/// </summary>
|
||||
public Action<bool> OnReceivedRules;
|
||||
|
||||
/// <summary>
|
||||
/// List of server rules. Use HasRules to see if this is safe to access.
|
||||
/// </summary>
|
||||
public Dictionary<string, string> Rules;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if this server has rules
|
||||
/// </summary>
|
||||
public bool HasRules { get { return Rules != null && Rules.Count > 0; } }
|
||||
|
||||
internal Interop.ServerRules RulesRequest;
|
||||
|
||||
/// <summary>
|
||||
/// Populates Rules for this server
|
||||
/// </summary>
|
||||
public void FetchRules()
|
||||
{
|
||||
if ( RulesRequest != null )
|
||||
return;
|
||||
|
||||
Rules = new Dictionary<string, string>();
|
||||
|
||||
RulesRequest = new Interop.ServerRules( this, Address, QueryPort );
|
||||
}
|
||||
|
||||
internal void OnServerRulesReceiveFinished( bool Success )
|
||||
{
|
||||
RulesRequest.Dispose();
|
||||
RulesRequest = null;
|
||||
|
||||
if ( OnReceivedRules != null )
|
||||
OnReceivedRules( Success );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,157 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Valve.Steamworks;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public partial class Client : IDisposable
|
||||
{
|
||||
private ServerList _serverlist;
|
||||
|
||||
public ServerList ServerList
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _serverlist == null )
|
||||
_serverlist = new ServerList { client = this };
|
||||
|
||||
return _serverlist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class ServerList
|
||||
{
|
||||
|
||||
public class Filter : List<KeyValuePair<string, string>>
|
||||
{
|
||||
public void Add( string k, string v )
|
||||
{
|
||||
Add( new KeyValuePair<string, string>( k, v ) );
|
||||
}
|
||||
|
||||
internal IntPtr NativeArray;
|
||||
private IntPtr m_pArrayEntries;
|
||||
|
||||
internal void Start()
|
||||
{
|
||||
var filters = this.Select( x =>
|
||||
{
|
||||
return new MatchMakingKeyValuePair_t()
|
||||
{
|
||||
m_szKey = x.Key,
|
||||
m_szValue = x.Value
|
||||
};
|
||||
|
||||
} ).ToArray();
|
||||
|
||||
int sizeOfMMKVP = Marshal.SizeOf(typeof(MatchMakingKeyValuePair_t));
|
||||
NativeArray = Marshal.AllocHGlobal( Marshal.SizeOf( typeof( IntPtr ) ) * filters.Length );
|
||||
m_pArrayEntries = Marshal.AllocHGlobal( sizeOfMMKVP * filters.Length );
|
||||
|
||||
for ( int i = 0; i < filters.Length; ++i )
|
||||
{
|
||||
Marshal.StructureToPtr( filters[i], new IntPtr( m_pArrayEntries.ToInt64() + ( i * sizeOfMMKVP ) ), false );
|
||||
}
|
||||
|
||||
Marshal.WriteIntPtr( NativeArray, m_pArrayEntries );
|
||||
}
|
||||
|
||||
internal void Free()
|
||||
{
|
||||
if ( m_pArrayEntries != IntPtr.Zero )
|
||||
{
|
||||
Marshal.FreeHGlobal( m_pArrayEntries );
|
||||
}
|
||||
|
||||
if ( NativeArray != IntPtr.Zero )
|
||||
{
|
||||
Marshal.FreeHGlobal( NativeArray );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal Client client;
|
||||
|
||||
[StructLayout( LayoutKind.Sequential )]
|
||||
private struct MatchPair
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public string key;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public string value;
|
||||
}
|
||||
|
||||
public Request Internet( Filter filter )
|
||||
{
|
||||
filter.Start();
|
||||
|
||||
var request = new Request( client );
|
||||
request.AddRequest( client.native.servers.RequestInternetServerList( client.AppId, filter.NativeArray, filter.Count, IntPtr.Zero ) );
|
||||
|
||||
filter.Free();
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
public Request Custom( IEnumerable<string> serverList )
|
||||
{
|
||||
var request = new Request( client );
|
||||
request.ServerList = serverList;
|
||||
request.StartCustomQuery();
|
||||
return request;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// History filters don't seem to work, so we don't bother.
|
||||
/// You should apply them post process'dly
|
||||
/// </summary>
|
||||
public Request History()
|
||||
{
|
||||
var request = new Request( client );
|
||||
request.AddRequest( client.native.servers.RequestHistoryServerList( client.AppId, new IntPtr[] { }, IntPtr.Zero ) );
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Favourite filters don't seem to work, so we don't bother.
|
||||
/// You should apply them post process'dly
|
||||
/// </summary>
|
||||
public Request Favourites()
|
||||
{
|
||||
var request = new Request( client );
|
||||
request.AddRequest( client.native.servers.RequestFavoritesServerList( client.AppId, new IntPtr[] { }, IntPtr.Zero ) );
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
public void AddToHistory( Server server )
|
||||
{
|
||||
// client.native.matchmaking
|
||||
}
|
||||
|
||||
public void RemoveFromHistory( Server server )
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public void AddToFavourite( Server server )
|
||||
{
|
||||
// client.native.matchmaking
|
||||
}
|
||||
|
||||
public void RemoveFromFavourite( Server server )
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public bool IsFavourite( Server server )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,509 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.IO;
|
||||
|
||||
internal class SourceServerQuery :IDisposable
|
||||
{
|
||||
public class PlayersResponse
|
||||
{
|
||||
public short player_count;
|
||||
public List<Player> players = new List<Player>();
|
||||
|
||||
public class Player
|
||||
{
|
||||
public String name { get; set; }
|
||||
public int score { get; set; }
|
||||
public float playtime { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
private IPEndPoint endPoint;
|
||||
|
||||
private Socket socket;
|
||||
private UdpClient client;
|
||||
|
||||
// send & receive timeouts
|
||||
private int send_timeout = 2500;
|
||||
private int receive_timeout = 2500;
|
||||
|
||||
// raw response returned from the server
|
||||
private byte[] raw_data;
|
||||
|
||||
private int offset = 0;
|
||||
|
||||
// constants
|
||||
private readonly byte[] FFFFFFFF = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
|
||||
public SourceServerQuery( String ip, int port )
|
||||
{
|
||||
this.endPoint = new IPEndPoint( IPAddress.Parse( ip ), port );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of currently in-game clients on the specified gameserver.
|
||||
/// <b>Please note:</b> the playtime is stored as a float in <i>seconds</i>, you might want to convert it.
|
||||
///
|
||||
/// See https://developer.valvesoftware.com/wiki/Server_queries#A2S_PLAYER for more Information
|
||||
/// </summary>
|
||||
/// <returns>A PLayersResponse Object containing the name, score and playtime of each player</returns>
|
||||
public PlayersResponse GetPlayerList()
|
||||
{
|
||||
// open socket if not already open
|
||||
this.GetSocket();
|
||||
// we don't need the header, so set pointer to where the payload begins
|
||||
this.offset = 5;
|
||||
|
||||
try
|
||||
{
|
||||
PlayersResponse pr = new PlayersResponse();
|
||||
|
||||
// since A2S_PLAYER requests require a valid challenge, get it first
|
||||
byte[] challenge = this.GetChallenge(0x55, true);
|
||||
|
||||
byte[] request = new byte[challenge.Length + this.FFFFFFFF.Length + 1];
|
||||
Array.Copy( this.FFFFFFFF, 0, request, 0, this.FFFFFFFF.Length );
|
||||
request[this.FFFFFFFF.Length] = 0x55;
|
||||
Array.Copy( challenge, 0, request, this.FFFFFFFF.Length + 1, challenge.Length );
|
||||
|
||||
this.socket.Send( request );
|
||||
|
||||
// MODIFIED BY ZACKBOE
|
||||
// Increased byte size from 1024 in order to receive more player data
|
||||
// Previously returned a socket exception at >~ 51 players.
|
||||
this.raw_data = new byte[2048];
|
||||
// END MODIFICATION
|
||||
this.socket.Receive( this.raw_data );
|
||||
|
||||
byte player_count = this.ReadByte();
|
||||
|
||||
// fill up the list of players
|
||||
for ( int i = 0; i < player_count; i++ )
|
||||
{
|
||||
this.ReadByte();
|
||||
|
||||
PlayersResponse.Player p = new PlayersResponse.Player();
|
||||
|
||||
p.name = this.ReadString();
|
||||
p.score = this.ReadInt32();
|
||||
p.playtime = this.ReadFloat();
|
||||
|
||||
pr.players.Add( p );
|
||||
}
|
||||
|
||||
pr.player_count = player_count;
|
||||
|
||||
return pr;
|
||||
}
|
||||
catch ( SocketException e )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of all publically available CVars ("rules") from the server.
|
||||
/// <b>Note:</b> Due to a bug in the Source Engine, it might happen that some CVars/values are cut off.
|
||||
///
|
||||
/// Example: mp_idlemaxtime = [nothing]
|
||||
/// Only Valve can fix that.
|
||||
/// </summary>
|
||||
/// <returns>A RulesResponse Object containing a Name-Value pair of each CVar</returns>
|
||||
public Dictionary<string, string> GetRules()
|
||||
{
|
||||
// open udpclient if not already open
|
||||
this.GetClient();
|
||||
|
||||
try
|
||||
{
|
||||
var d = new Dictionary<string, string>();
|
||||
|
||||
// similar to A2S_PLAYER requests, A2S_RULES require a valid challenge
|
||||
byte[] challenge = this.GetChallenge(0x56, false);
|
||||
|
||||
byte[] request = new byte[challenge.Length + this.FFFFFFFF.Length + 1];
|
||||
Array.Copy( this.FFFFFFFF, 0, request, 0, this.FFFFFFFF.Length );
|
||||
request[this.FFFFFFFF.Length] = 0x56;
|
||||
Array.Copy( challenge, 0, request, this.FFFFFFFF.Length + 1, challenge.Length );
|
||||
|
||||
this.client.Send( request, request.Length );
|
||||
|
||||
//
|
||||
// Since A2S_RULES responses might be split up into several packages/compressed, we have to do a special handling of them
|
||||
//
|
||||
int bytesRead;
|
||||
|
||||
// this will keep our assembled message
|
||||
byte[] buffer = new byte[4096];
|
||||
|
||||
// send first request
|
||||
|
||||
this.raw_data = this.client.Receive( ref this.endPoint );
|
||||
|
||||
bytesRead = this.raw_data.Length;
|
||||
|
||||
// reset pointer
|
||||
this.offset = 0;
|
||||
|
||||
int is_split = this.ReadInt32();
|
||||
int requestid = this.ReadInt32();
|
||||
|
||||
this.offset = 4;
|
||||
|
||||
// response is split up into several packets
|
||||
if ( this.PacketIsSplit( is_split ) )
|
||||
{
|
||||
bool isCompressed = false;
|
||||
byte[] splitData;
|
||||
int packetCount, packetNumber, requestId;
|
||||
int packetsReceived = 1;
|
||||
int packetChecksum = 0;
|
||||
int packetSplit = 0;
|
||||
short splitSize;
|
||||
int uncompressedSize = 0;
|
||||
List<byte[]> splitPackets = new List<byte[]>();
|
||||
|
||||
do
|
||||
{
|
||||
// unique request id
|
||||
requestId = this.ReverseBytes( this.ReadInt32() );
|
||||
isCompressed = this.PacketIsCompressed( requestId );
|
||||
|
||||
packetCount = this.ReadByte();
|
||||
packetNumber = this.ReadByte() + 1;
|
||||
// so we know how big our byte arrays have to be
|
||||
splitSize = this.ReadInt16();
|
||||
splitSize -= 4; // fix
|
||||
|
||||
if ( packetsReceived == 1 )
|
||||
{
|
||||
for ( int i = 0; i < packetCount; i++ )
|
||||
{
|
||||
splitPackets.Add( new byte[] { } );
|
||||
}
|
||||
}
|
||||
|
||||
// if the packets are compressed, get some data to decompress them
|
||||
if ( isCompressed )
|
||||
{
|
||||
uncompressedSize = ReverseBytes( this.ReadInt32() );
|
||||
packetChecksum = ReverseBytes( this.ReadInt32() );
|
||||
}
|
||||
|
||||
// ommit header in first packet
|
||||
if ( packetNumber == 1 ) this.ReadInt32();
|
||||
|
||||
splitData = new byte[splitSize];
|
||||
splitPackets[packetNumber - 1] = this.ReadBytes();
|
||||
|
||||
// fixes a case where the returned package might still contain a character after the last \0 terminator (truncated name => value)
|
||||
// please note: this therefore also removes the value of said variable, but atleast the program won't crash
|
||||
if ( splitPackets[packetNumber - 1].Length - 1 > 0 && splitPackets[packetNumber - 1][splitPackets[packetNumber - 1].Length - 1] != 0x00 )
|
||||
{
|
||||
splitPackets[packetNumber - 1][splitPackets[packetNumber - 1].Length - 1] = 0x00;
|
||||
}
|
||||
|
||||
// reset pointer again, so we can copy over the contents
|
||||
this.offset = 0;
|
||||
|
||||
if ( packetsReceived < packetCount )
|
||||
{
|
||||
|
||||
this.raw_data = this.client.Receive( ref this.endPoint );
|
||||
bytesRead = this.raw_data.Length;
|
||||
|
||||
// continue with the next packets
|
||||
packetSplit = this.ReadInt32();
|
||||
packetsReceived++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// all packets received
|
||||
bytesRead = 0;
|
||||
}
|
||||
}
|
||||
while ( packetsReceived <= packetCount && bytesRead > 0 && packetSplit == -2 );
|
||||
|
||||
// decompress
|
||||
if ( isCompressed )
|
||||
{
|
||||
buffer = ReassemblePacket( splitPackets, true, uncompressedSize, packetChecksum );
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = ReassemblePacket( splitPackets, false, 0, 0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = this.raw_data;
|
||||
}
|
||||
|
||||
// move our final result over to handle it
|
||||
this.raw_data = buffer;
|
||||
|
||||
// omitting header
|
||||
this.offset += 1;
|
||||
var count = this.ReadInt16();
|
||||
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
var k = this.ReadString();
|
||||
var v = this.ReadString();
|
||||
|
||||
if ( !d.ContainsKey( k ) )
|
||||
d.Add( k, v );
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
catch ( SocketException e )
|
||||
{
|
||||
Console.WriteLine( e );
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close all currently open socket/UdpClient connections
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if ( this.socket != null ) this.socket.Close();
|
||||
if ( this.client != null ) this.client.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open up a new Socket-based connection to a server, if not already open.
|
||||
/// </summary>
|
||||
private void GetSocket()
|
||||
{
|
||||
if ( this.socket == null )
|
||||
{
|
||||
this.socket = new Socket(
|
||||
AddressFamily.InterNetwork,
|
||||
SocketType.Dgram,
|
||||
ProtocolType.Udp );
|
||||
|
||||
this.socket.SendTimeout = this.send_timeout;
|
||||
this.socket.ReceiveTimeout = this.receive_timeout;
|
||||
|
||||
this.socket.Connect( this.endPoint );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new UdpClient connection to a server (mostly used for multi-packet answers)
|
||||
/// </summary>
|
||||
private void GetClient()
|
||||
{
|
||||
if ( this.client == null )
|
||||
{
|
||||
this.client = new UdpClient();
|
||||
this.client.Connect( this.endPoint );
|
||||
this.client.DontFragment = true;
|
||||
|
||||
this.client.Client.SendTimeout = this.send_timeout;
|
||||
this.client.Client.ReceiveTimeout = this.receive_timeout;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reassmble a multi-packet response.
|
||||
/// </summary>
|
||||
/// <param name="splitPackets">The packets to assemble</param>
|
||||
/// <param name="isCompressed">true: packets are compressed; false: not</param>
|
||||
/// <param name="uncompressedSize">The size of the message after decompression (for comparison)</param>
|
||||
/// <param name="packetChecksum">Validation of the result</param>
|
||||
/// <returns>A byte-array containing all packets assembled together/decompressed.</returns>
|
||||
private byte[] ReassemblePacket( List<byte[]> splitPackets, bool isCompressed, int uncompressedSize, int packetChecksum )
|
||||
{
|
||||
byte[] packetData, tmpData;
|
||||
packetData = new byte[0];
|
||||
|
||||
foreach ( byte[] splitPacket in splitPackets )
|
||||
{
|
||||
if ( splitPacket == null )
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
tmpData = packetData;
|
||||
packetData = new byte[tmpData.Length + splitPacket.Length];
|
||||
|
||||
MemoryStream memStream = new MemoryStream(packetData);
|
||||
memStream.Write( tmpData, 0, tmpData.Length );
|
||||
memStream.Write( splitPacket, 0, splitPacket.Length );
|
||||
}
|
||||
|
||||
if ( isCompressed )
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
return packetData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invert the Byte-order Mark of an value, used for compatibility between Little <-> Large BOM
|
||||
/// </summary>
|
||||
/// <param name="value">The value to invert</param>
|
||||
/// <returns>BOM-inversed value (if needed), otherwise the original value</returns>
|
||||
private int ReverseBytes( int value )
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
if ( BitConverter.IsLittleEndian )
|
||||
{
|
||||
Array.Reverse( bytes );
|
||||
}
|
||||
return BitConverter.ToInt32( bytes, 0 );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine whetever or not a message is compressed.
|
||||
/// Simply detects if the most significant bit is 1.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to check</param>
|
||||
/// <returns>true, if message is compressed, false otherwise</returns>
|
||||
private bool PacketIsCompressed( int value )
|
||||
{
|
||||
return ( value & 0x8000 ) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine whetever or not a message is split up.
|
||||
/// </summary>
|
||||
/// <param name="paket">The value to check</param>
|
||||
/// <returns>true, if message is split up, false otherwise</returns>
|
||||
private bool PacketIsSplit( int paket )
|
||||
{
|
||||
return ( paket == -2 );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request the 4-byte challenge id from the server, required for A2S_RULES and A2S_PLAYER.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of message to request the challenge for (see constants)</param>
|
||||
/// <param name="socket">Request method to use (performance reasons)</param>
|
||||
/// <returns>A Byte Array (4-bytes) containing the challenge</returns>
|
||||
private Byte[] GetChallenge( byte type, bool socket = true )
|
||||
{
|
||||
byte[] request = new byte[this.FFFFFFFF.Length + this.FFFFFFFF.Length + 1];
|
||||
Array.Copy( this.FFFFFFFF, 0, request, 0, this.FFFFFFFF.Length );
|
||||
request[FFFFFFFF.Length] = type;
|
||||
Array.Copy( this.FFFFFFFF, 0, request, this.FFFFFFFF.Length + 1, this.FFFFFFFF.Length );
|
||||
|
||||
byte[] raw_response = new byte[24];
|
||||
byte[] challenge = new byte[4];
|
||||
|
||||
// using sockets
|
||||
if ( socket )
|
||||
{
|
||||
this.socket.Send( request );
|
||||
this.socket.Receive( raw_response );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.client.Send( request, request.Length );
|
||||
raw_response = this.client.Receive( ref this.endPoint );
|
||||
}
|
||||
|
||||
Array.Copy( raw_response, 5, challenge, 0, 4 ); // change this valve modifies the protocol!
|
||||
|
||||
return challenge;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a single byte value from our raw data.
|
||||
/// </summary>
|
||||
/// <returns>A single Byte at the next Offset Address</returns>
|
||||
private Byte ReadByte()
|
||||
{
|
||||
byte[] b = new byte[1];
|
||||
Array.Copy( this.raw_data, this.offset, b, 0, 1 );
|
||||
|
||||
this.offset++;
|
||||
return b[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read all remaining Bytes from our raw data.
|
||||
/// Used for multi-packet responses.
|
||||
/// </summary>
|
||||
/// <returns>All remaining data</returns>
|
||||
private Byte[] ReadBytes()
|
||||
{
|
||||
int size = (this.raw_data.Length - this.offset - 4);
|
||||
if ( size < 1 ) return new Byte[] { };
|
||||
|
||||
byte[] b = new byte[size];
|
||||
Array.Copy( this.raw_data, this.offset, b, 0, this.raw_data.Length - this.offset - 4 );
|
||||
|
||||
this.offset += ( this.raw_data.Length - this.offset - 4 );
|
||||
return b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a 32-Bit Integer value from the next offset address.
|
||||
/// </summary>
|
||||
/// <returns>The Int32 Value found at the offset address</returns>
|
||||
private Int32 ReadInt32()
|
||||
{
|
||||
byte[] b = new byte[4];
|
||||
Array.Copy( this.raw_data, this.offset, b, 0, 4 );
|
||||
|
||||
this.offset += 4;
|
||||
return BitConverter.ToInt32( b, 0 );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a 16-Bit Integer (also called "short") value from the next offset address.
|
||||
/// </summary>
|
||||
/// <returns>The Int16 Value found at the offset address</returns>
|
||||
private Int16 ReadInt16()
|
||||
{
|
||||
byte[] b = new byte[2];
|
||||
Array.Copy( this.raw_data, this.offset, b, 0, 2 );
|
||||
|
||||
this.offset += 2;
|
||||
return BitConverter.ToInt16( b, 0 );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Float value from the next offset address.
|
||||
/// </summary>
|
||||
/// <returns>The Float Value found at the offset address</returns>
|
||||
private float ReadFloat()
|
||||
{
|
||||
byte[] b = new byte[4];
|
||||
Array.Copy( this.raw_data, this.offset, b, 0, 4 );
|
||||
|
||||
this.offset += 4;
|
||||
return BitConverter.ToSingle( b, 0 );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a String until its end starting from the next offset address.
|
||||
/// Reading stops once the method detects a 0x00 Character at the next position (\0 terminator)
|
||||
/// </summary>
|
||||
/// <returns>The String read</returns>
|
||||
private String ReadString()
|
||||
{
|
||||
byte[] cache = new byte[1] { 0x01 };
|
||||
String output = "";
|
||||
|
||||
while ( cache[0] != 0x00 )
|
||||
{
|
||||
if ( this.offset == this.raw_data.Length ) break; // fixes Valve's inability to code a proper query protocol
|
||||
Array.Copy( this.raw_data, this.offset, cache, 0, 1 );
|
||||
this.offset++;
|
||||
|
||||
if ( cache[0] != 0x00)
|
||||
output += Encoding.UTF8.GetString( cache );
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public partial class Client : IDisposable
|
||||
{
|
||||
Stats _stats;
|
||||
|
||||
public Stats Stats
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( _stats == null )
|
||||
_stats = new Stats( this );
|
||||
|
||||
return _stats;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Stats
|
||||
{
|
||||
internal Client client;
|
||||
|
||||
internal Stats( Client c )
|
||||
{
|
||||
client = c;
|
||||
}
|
||||
|
||||
public void UpdateStats()
|
||||
{
|
||||
client.native.userstats.RequestCurrentStats();
|
||||
}
|
||||
|
||||
public void UpdateGlobalStats( int days = 1 )
|
||||
{
|
||||
client.native.userstats.GetNumberOfCurrentPlayers();
|
||||
client.native.userstats.RequestGlobalAchievementPercentages();
|
||||
client.native.userstats.RequestGlobalStats( days );
|
||||
}
|
||||
|
||||
public int GetInt( string name )
|
||||
{
|
||||
int data = 0;
|
||||
client.native.userstats.GetStat( name, ref data );
|
||||
return data;
|
||||
}
|
||||
|
||||
public long GetGlobalInt( string name )
|
||||
{
|
||||
long data = 0;
|
||||
client.native.userstats.GetGlobalStat( name, ref data );
|
||||
return data;
|
||||
}
|
||||
|
||||
public float GetFloat( string name )
|
||||
{
|
||||
float data = 0;
|
||||
client.native.userstats.GetStat0( name, ref data );
|
||||
return data;
|
||||
}
|
||||
|
||||
public double GetGlobalFloat( string name )
|
||||
{
|
||||
double data = 0;
|
||||
client.native.userstats.GetGlobalStat0( name, ref data );
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,162 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public class Voice : IDisposable
|
||||
{
|
||||
const int ReadBufferSize = 1024 * 128;
|
||||
const int UncompressBufferSize = 1024 * 256;
|
||||
|
||||
internal Client client;
|
||||
|
||||
internal IntPtr ReadCompressedBuffer;
|
||||
internal IntPtr ReadUncompressedBuffer;
|
||||
|
||||
internal IntPtr UncompressBuffer;
|
||||
|
||||
public Action<IntPtr, int> OnCompressedData;
|
||||
public Action<IntPtr, int> OnUncompressedData;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the optimal sample rate for voice - according to Steam
|
||||
/// </summary>
|
||||
public uint OptimalSampleRate
|
||||
{
|
||||
get { return client.native.user.GetVoiceOptimalSampleRate(); }
|
||||
}
|
||||
|
||||
private bool _wantsrecording = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// If set to true we are listening to the mic.
|
||||
/// You should usually toggle this with the press of a key for push to talk.
|
||||
/// </summary>
|
||||
public bool WantsRecording
|
||||
{
|
||||
get { return _wantsrecording; }
|
||||
set
|
||||
{
|
||||
_wantsrecording = value;
|
||||
|
||||
if ( value )
|
||||
{
|
||||
client.native.user.StartVoiceRecording();
|
||||
}
|
||||
else
|
||||
{
|
||||
client.native.user.StopVoiceRecording();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The last time voice was detected, recorded
|
||||
/// </summary>
|
||||
public DateTime LastVoiceRecordTime { get; private set; }
|
||||
|
||||
public TimeSpan TimeSinceLastVoiceRecord { get { return DateTime.Now.Subtract( LastVoiceRecordTime ); } }
|
||||
|
||||
public bool IsRecording = false;
|
||||
|
||||
/// <summary>
|
||||
/// If set we will capture the audio at this rate. If unset (set to 0) will capture at OptimalSampleRate
|
||||
/// </summary>
|
||||
public uint DesiredSampleRate = 0;
|
||||
|
||||
public Voice( Client client )
|
||||
{
|
||||
this.client = client;
|
||||
|
||||
ReadCompressedBuffer = Marshal.AllocHGlobal( ReadBufferSize );
|
||||
ReadUncompressedBuffer = Marshal.AllocHGlobal( ReadBufferSize );
|
||||
UncompressBuffer = Marshal.AllocHGlobal( UncompressBufferSize );
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Marshal.FreeHGlobal( ReadCompressedBuffer );
|
||||
Marshal.FreeHGlobal( ReadUncompressedBuffer );
|
||||
|
||||
Marshal.FreeHGlobal( UncompressBuffer );
|
||||
}
|
||||
|
||||
internal void Update()
|
||||
{
|
||||
if ( OnCompressedData == null && OnUncompressedData == null )
|
||||
return;
|
||||
|
||||
|
||||
uint bufferRegularLastWrite = 0;
|
||||
uint bufferCompressedLastWrite = 0;
|
||||
|
||||
Valve.Steamworks.EVoiceResult result = (Valve.Steamworks.EVoiceResult) client.native.user.GetVoice( OnCompressedData != null, ReadCompressedBuffer, ReadBufferSize, ref bufferCompressedLastWrite,
|
||||
OnUncompressedData != null, (IntPtr) ReadUncompressedBuffer, ReadBufferSize, ref bufferRegularLastWrite,
|
||||
DesiredSampleRate == 0 ? OptimalSampleRate : DesiredSampleRate );
|
||||
|
||||
Console.WriteLine( result );
|
||||
|
||||
IsRecording = true;
|
||||
|
||||
if ( result == Valve.Steamworks.EVoiceResult.k_EVoiceResultOK )
|
||||
{
|
||||
if ( OnCompressedData != null && bufferCompressedLastWrite > 0 )
|
||||
{
|
||||
OnCompressedData( ReadCompressedBuffer, (int)bufferCompressedLastWrite );
|
||||
}
|
||||
|
||||
if ( OnUncompressedData != null && bufferRegularLastWrite > 0 )
|
||||
{
|
||||
OnUncompressedData( ReadUncompressedBuffer, (int)bufferRegularLastWrite );
|
||||
}
|
||||
|
||||
LastVoiceRecordTime = DateTime.Now;
|
||||
}
|
||||
|
||||
if ( result == Valve.Steamworks.EVoiceResult.k_EVoiceResultNotRecording ||
|
||||
result == Valve.Steamworks.EVoiceResult.k_EVoiceResultNotInitialized )
|
||||
IsRecording = false;
|
||||
|
||||
}
|
||||
|
||||
public unsafe bool Decompress( byte[] input, MemoryStream output, uint samepleRate = 0 )
|
||||
{
|
||||
fixed ( byte* p = input )
|
||||
{
|
||||
return Decompress( (IntPtr)p, 0, input.Length, output, samepleRate );
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe bool Decompress( IntPtr input, int inputoffset, int inputsize, MemoryStream output, uint samepleRate = 0 )
|
||||
{
|
||||
if ( samepleRate == 0 )
|
||||
samepleRate = OptimalSampleRate;
|
||||
|
||||
uint bytesOut = 0;
|
||||
var result = (Valve.Steamworks.EVoiceResult) client.native.user.DecompressVoice( (IntPtr)( ((byte*)input) + inputoffset ), (uint) inputsize, UncompressBuffer, UncompressBufferSize, ref bytesOut, samepleRate );
|
||||
|
||||
if ( bytesOut > 0 )
|
||||
output.SetLength( bytesOut );
|
||||
|
||||
if ( result == Valve.Steamworks.EVoiceResult.k_EVoiceResultOK )
|
||||
{
|
||||
if ( output.Capacity < bytesOut )
|
||||
output.Capacity = (int) bytesOut;
|
||||
|
||||
output.SetLength( bytesOut );
|
||||
Marshal.Copy( UncompressBuffer, output.GetBuffer(), 0, (int) bytesOut );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Facepunch.Steamworks
|
||||
{
|
||||
public static class Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Some platforms allow/need CallingConvention.ThisCall. If you're crashing with argument null
|
||||
/// errors on certain platforms, try flipping this to true.
|
||||
///
|
||||
/// I owe this logic to Riley Labrecque's hard work on Steamworks.net - I don't have the knowledge
|
||||
/// or patience to find this shit on my own, so massive thanks to him. And also massive thanks to him
|
||||
/// for releasing his shit open source under the MIT license so we can all learn and iterate.
|
||||
///
|
||||
/// </summary>
|
||||
public static bool UseThisCall { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Set this to true on Linux and OSX
|
||||
/// </summary>
|
||||
public static bool PackSmall { get; set; } = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The Native dll to look for. This is the steam_api.dll renamed.
|
||||
/// We need to rename the dll anyway because we can't dynamically choose the library
|
||||
/// ie, we can't load steam_api64.dll on windows 64 platforms. So instead we choose to
|
||||
/// keep the library name the same.
|
||||
///
|
||||
/// This is exposed only for the benefit of implementation - and cannot be changed at runtime.
|
||||
/// </summary>
|
||||
public const string LibraryName = "FacepunchSteamworksApi";
|
||||
}
|
||||
}
|
20
Facepunch.Steamworks/Enum/LeaderboardDisplay.cs
Normal file
20
Facepunch.Steamworks/Enum/LeaderboardDisplay.cs
Normal file
@ -0,0 +1,20 @@
|
||||
namespace Steamworks.Data
|
||||
{
|
||||
public enum LeaderboardDisplay : int
|
||||
{
|
||||
/// <summary>
|
||||
/// The score is just a simple numerical value
|
||||
/// </summary>
|
||||
Numeric = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The score represents a time, in seconds
|
||||
/// </summary>
|
||||
TimeSeconds = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The score represents a time, in milliseconds
|
||||
/// </summary>
|
||||
TimeMilliSeconds = 3,
|
||||
}
|
||||
}
|
15
Facepunch.Steamworks/Enum/LeaderboardSort.cs
Normal file
15
Facepunch.Steamworks/Enum/LeaderboardSort.cs
Normal file
@ -0,0 +1,15 @@
|
||||
namespace Steamworks.Data
|
||||
{
|
||||
public enum LeaderboardSort : int
|
||||
{
|
||||
/// <summary>
|
||||
/// The top-score is the lowest number
|
||||
/// </summary>
|
||||
Ascending = 1,
|
||||
|
||||
/// <summary>
|
||||
/// The top-score is the highest number
|
||||
/// </summary>
|
||||
Descending = 2,
|
||||
}
|
||||
}
|
42
Facepunch.Steamworks/Enum/SendType.cs
Normal file
42
Facepunch.Steamworks/Enum/SendType.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using System;
|
||||
|
||||
namespace Steamworks.Data
|
||||
{
|
||||
[Flags]
|
||||
public enum SendType : int
|
||||
{
|
||||
/// <summary>
|
||||
/// Send the message unreliably. Can be lost. Messages *can* be larger than a
|
||||
/// single MTU (UDP packet), but there is no retransmission, so if any piece
|
||||
/// of the message is lost, the entire message will be dropped.
|
||||
///
|
||||
/// The sending API does have some knowledge of the underlying connection, so
|
||||
/// if there is no NAT-traversal accomplished or there is a recognized adjustment
|
||||
/// happening on the connection, the packet will be batched until the connection
|
||||
/// is open again.
|
||||
/// </summary>
|
||||
Unreliable = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Disable Nagle's algorithm.
|
||||
/// By default, Nagle's algorithm is applied to all outbound messages. This means
|
||||
/// that the message will NOT be sent immediately, in case further messages are
|
||||
/// sent soon after you send this, which can be grouped together. Any time there
|
||||
/// is enough buffered data to fill a packet, the packets will be pushed out immediately,
|
||||
/// but partially-full packets not be sent until the Nagle timer expires.
|
||||
/// </summary>
|
||||
NoNagle = 1 << 0,
|
||||
|
||||
/// <summary>
|
||||
/// If the message cannot be sent very soon (because the connection is still doing some initial
|
||||
/// handshaking, route negotiations, etc), then just drop it. This is only applicable for unreliable
|
||||
/// messages. Using this flag on reliable messages is invalid.
|
||||
/// </summary>
|
||||
NoDelay = 1 << 2,
|
||||
|
||||
/// Reliable message send. Can send up to 0.5mb in a single message.
|
||||
/// Does fragmentation/re-assembly of messages under the hood, as well as a sliding window for
|
||||
/// efficient sends of large chunks of data.
|
||||
Reliable = 1 << 3
|
||||
}
|
||||
}
|
16
Facepunch.Steamworks/Facepunch.Steamworks.Posix.csproj
Normal file
16
Facepunch.Steamworks/Facepunch.Steamworks.Posix.csproj
Normal file
@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<AssemblyName>Facepunch.Steamworks.Posix</AssemblyName>
|
||||
<DefineConstants>$(DefineConstants);PLATFORM_POSIX</DefineConstants>
|
||||
<TargetFrameworks>netstandard2.1;net6.0;net46</TargetFrameworks>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>10</LangVersion>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RootNamespace>Steamworks</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="Facepunch.Steamworks.targets" />
|
||||
|
||||
</Project>
|
42
Facepunch.Steamworks/Facepunch.Steamworks.Win32.csproj
Normal file
42
Facepunch.Steamworks/Facepunch.Steamworks.Win32.csproj
Normal file
@ -0,0 +1,42 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<AssemblyName>Facepunch.Steamworks.Win32</AssemblyName>
|
||||
<DefineConstants>$(DefineConstants);PLATFORM_WIN32;PLATFORM_WIN</DefineConstants>
|
||||
<TargetFrameworks>netstandard2.1;net6.0;net46</TargetFrameworks>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
<RootNamespace>Steamworks</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<FrameworkPathOverride Condition="'$(TargetFramework)' == 'net40'">C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Profile\Client</FrameworkPathOverride>
|
||||
<Authors>Garry Newman</Authors>
|
||||
<PackageId>Facepunch.Steamworks.win32</PackageId>
|
||||
<PackageDescription>Steamworks implementation with an emphasis on making things easy. For Windows x86.</PackageDescription>
|
||||
<PackageProjectUrl>https://github.com/Facepunch/Facepunch.Steamworks</PackageProjectUrl>
|
||||
<PackageIcon>Facepunch.Steamworks.jpg</PackageIcon>
|
||||
<PackageTags>facepunch;steam;unity;steamworks;valve</PackageTags>
|
||||
<LangVersion>10</LangVersion>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<RepositoryUrl>https://github.com/Facepunch/Facepunch.Steamworks.git</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="Facepunch.Steamworks.jpg">
|
||||
<Pack>true</Pack>
|
||||
<PackagePath>/</PackagePath>
|
||||
</None>
|
||||
<None Include="steam_api.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<Pack>true</Pack>
|
||||
<PackagePath>content</PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="Facepunch.Steamworks.targets" />
|
||||
|
||||
</Project>
|
55
Facepunch.Steamworks/Facepunch.Steamworks.Win64.csproj
Normal file
55
Facepunch.Steamworks/Facepunch.Steamworks.Win64.csproj
Normal file
@ -0,0 +1,55 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<AssemblyName>Facepunch.Steamworks.Win64</AssemblyName>
|
||||
<DefineConstants>$(DefineConstants);PLATFORM_WIN64;PLATFORM_WIN;PLATFORM_64</DefineConstants>
|
||||
<TargetFrameworks>netstandard2.1;net6.0;net46</TargetFrameworks>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
<RootNamespace>Steamworks</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<FrameworkPathOverride Condition="'$(TargetFramework)' == 'net40'">C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Profile\Client</FrameworkPathOverride>
|
||||
<Authors>Garry Newman</Authors>
|
||||
<PackageId>Facepunch.Steamworks</PackageId>
|
||||
<PackageDescription>Steamworks implementation with an emphasis on making things easy. For Windows x64.</PackageDescription>
|
||||
<PackageProjectUrl>https://github.com/Facepunch/Facepunch.Steamworks</PackageProjectUrl>
|
||||
<PackageIcon>Facepunch.Steamworks.jpg</PackageIcon>
|
||||
<PackageTags>facepunch;steam;unity;steamworks;valve</PackageTags>
|
||||
<LangVersion>10</LangVersion>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<RepositoryUrl>https://github.com/Facepunch/Facepunch.Steamworks.git</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="Facepunch.Steamworks.jpg">
|
||||
<Pack>true</Pack>
|
||||
<PackagePath>/</PackagePath>
|
||||
</None>
|
||||
<None Include="steam_api64.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<Pack>true</Pack>
|
||||
<PackagePath>content</PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="Facepunch.Steamworks.targets" />
|
||||
|
||||
<Target Name="PostBuildHome" AfterTargets="PostBuildEvent" Condition="'$(Computername)'=='GarryBasementPc'">
|
||||
<Exec Command="Copy $(TargetDir)\Facepunch.Steamworks.Win64.* C:\plastic\RustMain\Assets\Plugins\Facepunch.Steamworks\" />
|
||||
<Exec Command="Copy $(TargetDir)\Facepunch.Steamworks.Posix.* C:\plastic\RustMain\Assets\Plugins\Facepunch.Steamworks\" />
|
||||
</Target>
|
||||
|
||||
<Target Name="PostBuildOffice" AfterTargets="PostBuildEvent" Condition="'$(Computername)'=='GARRYSOFFICEPC'">
|
||||
<Exec Command="Copy $(TargetDir)\Facepunch.Steamworks.Win64.* C:\Plastic\Rust\Assets\Plugins\Facepunch.Steamworks\" />
|
||||
<Exec Command="Copy $(TargetDir)\Facepunch.Steamworks.Posix.* C:\Plastic\Rust\Assets\Plugins\Facepunch.Steamworks\" />
|
||||
<Exec Command="Copy $(TargetDir)\Facepunch.Steamworks.Win64.* C:\Git\Facepunch.Steamworks.UnityTest\Assets\Steamworks" />
|
||||
<Exec Command="Copy $(TargetDir)\Facepunch.Steamworks.Win32.* C:\Git\Facepunch.Steamworks.UnityTest\Assets\Steamworks" />
|
||||
<Exec Command="Copy $(TargetDir)\Facepunch.Steamworks.Posix.* C:\Git\Facepunch.Steamworks.UnityTest\Assets\Steamworks" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user