1
1
var _ = require ( 'lodash' )
2
2
var events = require ( 'events' )
3
3
var fs = require ( 'fs' )
4
+ var fsExtra = require ( 'fs.extra' )
4
5
var Gamedig = require ( 'gamedig' )
6
+ var glob = require ( 'glob' )
7
+ var path = require ( 'path' )
5
8
var slugify = require ( 'slugify' )
6
9
7
10
var ArmaServer = require ( 'arma-server' )
@@ -134,6 +137,104 @@ Server.prototype.start = function () {
134
137
return this
135
138
}
136
139
140
+ var self = this
141
+
142
+ const requiredFileExtensions = [ '.dll' , '.exe' , '.so' , '.txt' ]
143
+ const serverFolders = [
144
+ 'addons' ,
145
+ 'argo' ,
146
+ 'battleye' ,
147
+ 'contact' ,
148
+ 'curator' ,
149
+ 'dll' ,
150
+ 'dta' ,
151
+ 'enoch' ,
152
+ 'expansion' ,
153
+ 'gm' ,
154
+ 'heli' ,
155
+ 'jets' ,
156
+ 'kart' ,
157
+ 'mark' ,
158
+ 'mpmissions' ,
159
+ 'orange' ,
160
+ 'tacops' ,
161
+ 'tank'
162
+ ]
163
+ const symlinkFolders = serverFolders . concat ( self . mods ) . concat ( config . serverMods )
164
+
165
+ return fs . promises . mkdtemp ( path . join ( self . config . path , 'arma-server-' ) )
166
+ . then ( ( serverFolder ) => {
167
+ self . virtualServerFolder = serverFolder
168
+ console . log ( 'Created virtual server folder:' , serverFolder )
169
+
170
+ return fs . promises . readdir ( self . config . path )
171
+ . then ( ( files ) => {
172
+ // Copy needed files, file symlinks on Windows are sketchy
173
+ const serverFiles = files . filter ( ( file ) => requiredFileExtensions . indexOf ( path . extname ( file ) ) >= 0 || path . basename ( file ) === 'arma3server' )
174
+ return Promise . all ( serverFiles . map ( ( file ) => {
175
+ return fs . promises . copyFile ( path . join ( self . config . path , file ) , path . join ( serverFolder , file ) )
176
+ } ) )
177
+ } )
178
+ . then ( ( ) => {
179
+ // Create virtual folders from default Arma and mods
180
+ return Promise . all ( symlinkFolders . map ( ( symlink ) => {
181
+ return fs . promises . access ( path . join ( self . config . path , symlink ) )
182
+ . then ( ( ) => {
183
+ return fs . promises . symlink ( path . join ( self . config . path , symlink ) , path . join ( serverFolder , symlink ) , 'junction' )
184
+ } )
185
+ . catch ( ( err ) => {
186
+ console . error ( 'Could create symlink for' , symlink , 'due to' , err )
187
+ } )
188
+ } ) )
189
+ } )
190
+ . then ( ( ) => {
191
+ // Copy needed keys, file symlinks on Windows are sketchy
192
+ const keysFolder = path . join ( serverFolder , 'keys' )
193
+ return fs . promises . mkdir ( keysFolder , { recursive : true } )
194
+ . then ( ( ) => {
195
+ const defaultKeysPath = path . join ( self . config . path , 'keys' )
196
+ const defaultKeysPromise = fs . promises . readdir ( defaultKeysPath )
197
+ . then ( ( files ) => files . filter ( ( file ) => path . extname ( file ) === '.bikey' ) )
198
+ . then ( ( files ) => files . map ( ( file ) => path . join ( defaultKeysPath , file ) ) )
199
+
200
+ const modKeysPromise = Promise . all ( self . mods . map ( mod => {
201
+ return new Promise ( ( resolve , reject ) => {
202
+ const modPath = path . join ( this . config . path , mod )
203
+ glob ( `${ modPath } /**/*.bikey` , function ( err , files ) {
204
+ if ( err ) {
205
+ return reject ( err )
206
+ }
207
+
208
+ return resolve ( files )
209
+ } )
210
+ } )
211
+ } ) ) . then ( ( modsFiles ) => modsFiles . flat ( ) )
212
+
213
+ return Promise . all ( [ defaultKeysPromise , modKeysPromise ] . map ( ( promise ) => {
214
+ return promise . then ( ( keyFiles ) => {
215
+ return Promise . all ( keyFiles . map ( ( keyFile ) => {
216
+ return fs . promises . copyFile ( keyFile , path . join ( keysFolder , path . basename ( keyFile ) ) )
217
+ } ) )
218
+ } )
219
+ } ) ) . catch ( ( err ) => {
220
+ console . error ( 'Error copying keys:' , err )
221
+ } )
222
+ } )
223
+ } )
224
+ . then ( ( ) => {
225
+ self . realStart ( serverFolder )
226
+ } )
227
+ . catch ( ( err ) => {
228
+ console . error ( 'Error creating virtual server folder:' , err )
229
+ } )
230
+ } )
231
+ }
232
+
233
+ Server . prototype . realStart = function ( path ) {
234
+ if ( this . instance ) {
235
+ return this
236
+ }
237
+
137
238
var parameters = this . getParameters ( )
138
239
var server = new ArmaServer . Server ( {
139
240
additionalConfigurationOptions : this . getAdditionalConfigurationOptions ( ) ,
@@ -154,7 +255,7 @@ Server.prototype.start = function () {
154
255
parameters : parameters ,
155
256
password : this . password ,
156
257
passwordAdmin : this . admin_password ,
157
- path : this . config . path ,
258
+ path : path ,
158
259
persistent : this . persistent ? 1 : 0 ,
159
260
platform : this . config . type ,
160
261
players : this . max_players ,
@@ -196,8 +297,18 @@ Server.prototype.start = function () {
196
297
self . instance = null
197
298
198
299
self . stopHeadlessClients ( )
199
-
200
- self . emit ( 'state' )
300
+ . then ( ( ) => {
301
+ if ( self . virtualServerFolder ) {
302
+ fsExtra . rmrf ( self . virtualServerFolder , function ( err ) {
303
+ if ( err ) {
304
+ console . log ( 'Error removing virtual server folder' , err )
305
+ }
306
+ } )
307
+ self . virtualServerFolder = null
308
+ }
309
+
310
+ self . emit ( 'state' )
311
+ } )
201
312
} )
202
313
203
314
instance . on ( 'error' , function ( err ) {
@@ -210,14 +321,14 @@ Server.prototype.start = function () {
210
321
self . queryStatus ( )
211
322
} , queryInterval )
212
323
213
- this . startHeadlessClients ( )
324
+ this . startHeadlessClients ( path )
214
325
215
326
this . emit ( 'state' )
216
327
217
328
return this
218
329
}
219
330
220
- Server . prototype . startHeadlessClients = function ( ) {
331
+ Server . prototype . startHeadlessClients = function ( path ) {
221
332
var parameters = this . getParameters ( )
222
333
var self = this
223
334
var headlessClientInstances = _ . times ( this . number_of_headless_clients , function ( i ) {
@@ -228,7 +339,7 @@ Server.prototype.startHeadlessClients = function () {
228
339
mods : self . mods ,
229
340
parameters : parameters ,
230
341
password : self . password ,
231
- path : self . config . path ,
342
+ path : path ,
232
343
platform : self . config . type ,
233
344
port : self . port
234
345
} )
@@ -293,9 +404,9 @@ Server.prototype.stop = function (cb) {
293
404
}
294
405
295
406
Server . prototype . stopHeadlessClients = function ( ) {
296
- this . headlessClientInstances . map ( function ( headlessClientInstance ) {
297
- headlessClientInstance . kill ( )
298
- } )
407
+ return Promise . all ( this . headlessClientInstances . map ( function ( headlessClientInstance ) {
408
+ return headlessClientInstance . kill ( )
409
+ } ) )
299
410
}
300
411
301
412
Server . prototype . toJSON = function ( ) {
0 commit comments