3
3
using EFT ;
4
4
using EFT . InventoryLogic ;
5
5
using EFT . UI ;
6
+ using Fika . Core . Coop . Matchmaker ;
6
7
using Fika . Core . Coop . Players ;
7
8
using Fika . Core . Networking ;
8
9
using JetBrains . Annotations ;
9
10
using System . IO ;
11
+ using UnityEngine ;
10
12
11
13
namespace Fika . Core . Coop . ClientClasses
12
14
{
@@ -30,34 +32,192 @@ public override void CallMalfunctionRepaired(Weapon weapon)
30
32
31
33
public override void Execute ( GClass2837 operation , [ CanBeNull ] Callback callback )
32
34
{
33
- base . Execute ( operation , callback ) ;
34
-
35
- // Do not replicate picking up quest items, throws an error on the other clients
36
- if ( operation is GClass2839 pickupOperation )
35
+ if ( MatchmakerAcceptPatches . IsServer )
37
36
{
38
- if ( pickupOperation . Item . Template . QuestItem )
37
+ HostInventoryOperationManager operationManager = new ( this , operation , callback ) ;
38
+ if ( vmethod_0 ( operationManager . operation ) )
39
39
{
40
+ operationManager . operation . vmethod_0 ( operationManager . HandleResult ) ;
41
+
42
+ // Do not replicate picking up quest items, throws an error on the other clients
43
+ if ( operation is GClass2839 pickupOperation )
44
+ {
45
+ if ( pickupOperation . Item . Template . QuestItem )
46
+ {
47
+ return ;
48
+ }
49
+ }
50
+
51
+ // TODO: Check for glass increments
52
+ if ( operation is GClass2870 )
53
+ {
54
+ return ;
55
+ }
56
+
57
+ InventoryPacket packet = new ( )
58
+ {
59
+ HasItemControllerExecutePacket = true
60
+ } ;
61
+
62
+ using MemoryStream memoryStream = new ( ) ;
63
+ using BinaryWriter binaryWriter = new ( memoryStream ) ;
64
+ binaryWriter . WritePolymorph ( GClass1632 . FromInventoryOperation ( operation , false ) ) ;
65
+ byte [ ] opBytes = memoryStream . ToArray ( ) ;
66
+ packet . ItemControllerExecutePacket = new ( )
67
+ {
68
+ CallbackId = operation . Id ,
69
+ OperationBytes = opBytes
70
+ } ;
71
+
72
+ CoopPlayer . PacketSender ? . InventoryPackets ? . Enqueue ( packet ) ;
73
+
40
74
return ;
41
75
}
76
+ operationManager . operation . Dispose ( ) ;
77
+ operationManager . callback ? . Fail ( $ "Can't execute { operationManager . operation } ", 1 ) ;
78
+ }
79
+ else if ( MatchmakerAcceptPatches . IsClient )
80
+ {
81
+ // Do not replicate picking up quest items, throws an error on the other clients
82
+ if ( operation is GClass2839 pickupOperation )
83
+ {
84
+ if ( pickupOperation . Item . Template . QuestItem )
85
+ {
86
+ base . Execute ( operation , callback ) ;
87
+ return ;
88
+ }
89
+ }
90
+
91
+ InventoryPacket packet = new ( )
92
+ {
93
+ HasItemControllerExecutePacket = true
94
+ } ;
95
+
96
+ ClientInventoryOperationManager clientOperationManager = new ( )
97
+ {
98
+ operation = operation ,
99
+ callback = callback ,
100
+ inventoryController = this
101
+ } ;
102
+
103
+ clientOperationManager . callback ??= new Callback ( ClientPlayer . Control0 . Class1400 . class1400_0 . method_0 ) ;
104
+ uint operationNum = AddOperationCallback ( operation , new Callback < EOperationStatus > ( clientOperationManager . HandleResult ) ) ;
105
+
106
+ using MemoryStream memoryStream = new ( ) ;
107
+ using BinaryWriter binaryWriter = new ( memoryStream ) ;
108
+ binaryWriter . WritePolymorph ( GClass1632 . FromInventoryOperation ( operation , false ) ) ;
109
+ byte [ ] opBytes = memoryStream . ToArray ( ) ;
110
+ packet . ItemControllerExecutePacket = new ( )
111
+ {
112
+ CallbackId = operationNum ,
113
+ OperationBytes = opBytes
114
+ } ;
115
+
116
+ CoopPlayer . PacketSender ? . InventoryPackets ? . Enqueue ( packet ) ;
117
+ }
118
+ }
119
+
120
+ private uint AddOperationCallback ( GClass2837 operation , Callback < EOperationStatus > callback )
121
+ {
122
+ ushort id = operation . Id ;
123
+ CoopPlayer . OperationCallbacks . Add ( id , callback ) ;
124
+ return id ;
125
+ }
126
+
127
+ private class HostInventoryOperationManager ( CoopClientInventoryController inventoryController , GClass2837 operation , Callback callback )
128
+ {
129
+ public readonly CoopClientInventoryController inventoryController = inventoryController ;
130
+ public GClass2837 operation = operation ;
131
+ public readonly Callback callback = callback ;
132
+
133
+ public void HandleResult ( IResult result )
134
+ {
135
+ if ( ! result . Succeed )
136
+ {
137
+ FikaPlugin . Instance . FikaLogger . LogError ( $ "[{ Time . frameCount } ][{ inventoryController . Name } ] { inventoryController . ID } - Local operation failed: { operation . Id } - { operation } \r \n Error: { result . Error } ") ;
138
+ }
139
+ callback ? . Invoke ( result ) ;
42
140
}
141
+ }
43
142
44
- InventoryPacket packet = new ( )
143
+ private class ClientInventoryOperationManager
144
+ {
145
+ public EOperationStatus ? serverOperationStatus ;
146
+ public EOperationStatus ? localOperationStatus ;
147
+ public GClass2837 operation ;
148
+ public Callback callback ;
149
+ public CoopClientInventoryController inventoryController ;
150
+
151
+ public void HandleResult ( Result < EOperationStatus > result )
45
152
{
46
- HasItemControllerExecutePacket = true
47
- } ;
48
-
49
- using MemoryStream memoryStream = new ( ) ;
50
- using BinaryWriter binaryWriter = new ( memoryStream ) ;
51
- binaryWriter . WritePolymorph ( GClass1632 . FromInventoryOperation ( operation , false ) ) ;
52
- byte [ ] opBytes = memoryStream . ToArray ( ) ;
53
- packet . ItemControllerExecutePacket = new ( )
153
+ ClientInventoryCallbackManager callbackManager = new ( )
154
+ {
155
+ clientOperationManager = this ,
156
+ result = result
157
+ } ;
158
+
159
+ if ( callbackManager . result . Succeed )
160
+ {
161
+ EOperationStatus value = callbackManager . result . Value ;
162
+ if ( value == EOperationStatus . Started )
163
+ {
164
+ localOperationStatus = EOperationStatus . Started ;
165
+ serverOperationStatus = EOperationStatus . Started ;
166
+ operation . vmethod_0 ( new Callback ( callbackManager . HandleResult ) , true ) ;
167
+ return ;
168
+ }
169
+ if ( value == EOperationStatus . Finished )
170
+ {
171
+ serverOperationStatus = EOperationStatus . Finished ;
172
+ if ( localOperationStatus == serverOperationStatus )
173
+ {
174
+ operation . Dispose ( ) ;
175
+ callback . Succeed ( ) ;
176
+ return ;
177
+ }
178
+ }
179
+ }
180
+ else
181
+ {
182
+ FikaPlugin . Instance . FikaLogger . LogError ( $ "{ inventoryController . ID } - Client operation rejected by server: { operation . Id } - { operation } \r \n Reason: { callbackManager . result . Error } ") ;
183
+ serverOperationStatus = EOperationStatus . Failed ;
184
+ localOperationStatus = EOperationStatus . Failed ;
185
+ operation . Dispose ( ) ;
186
+ callback . Invoke ( callbackManager . result ) ;
187
+ }
188
+ }
189
+ }
190
+
191
+ private class ClientInventoryCallbackManager
192
+ {
193
+ public Result < EOperationStatus > result ;
194
+ public ClientInventoryOperationManager clientOperationManager ;
195
+
196
+ public void HandleResult ( IResult executeResult )
54
197
{
55
- CallbackId = operation . Id ,
56
- OperationBytes = opBytes ,
57
- InventoryId = ID
58
- } ;
198
+ if ( ! executeResult . Succeed && ( executeResult . Error is not "skipped skippable" or "skipped _completed" ) )
199
+ {
200
+ FikaPlugin . Instance . FikaLogger . LogError ( $ "{ clientOperationManager . inventoryController . ID } - Client operation critical failure: { clientOperationManager . inventoryController . ID } - { clientOperationManager . operation } \r \n Error: { executeResult . Error } ") ;
201
+ }
202
+
203
+ clientOperationManager . localOperationStatus = EOperationStatus . Finished ;
59
204
60
- CoopPlayer . PacketSender ? . InventoryPackets ? . Enqueue ( packet ) ;
205
+ if ( clientOperationManager . localOperationStatus == clientOperationManager . serverOperationStatus )
206
+ {
207
+ clientOperationManager . operation . Dispose ( ) ;
208
+ clientOperationManager . callback . Invoke ( result ) ;
209
+ return ;
210
+ }
211
+
212
+ if ( clientOperationManager . serverOperationStatus != null )
213
+ {
214
+ if ( clientOperationManager . serverOperationStatus == EOperationStatus . Failed )
215
+ {
216
+ clientOperationManager . operation . Dispose ( ) ;
217
+ clientOperationManager . callback . Invoke ( result ) ;
218
+ }
219
+ }
220
+ }
61
221
}
62
222
}
63
- }
223
+ }
0 commit comments