-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathPerlUnitSync.pm
1486 lines (1407 loc) · 52.2 KB
/
PerlUnitSync.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# Perl UnitSync interface module for Win32 system
#
# Copyright (C) 2008-2023 Yann Riou <yaribzh@gmail.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Version 106.0b (2023/03/27)
package PerlUnitSync;
use strict;
use warnings;
use Carp 'croak';
use File::Spec::Functions qw'catfile catdir';
use constant {
DARWIN => $^O eq 'darwin',
MSWIN32 => $^O eq 'MSWin32',
};
use constant {
PACKAGE_PREFIX_LENGTH => length(__PACKAGE__)+2,
UNITSYNC_LIB_NAME => (MSWIN32 ? '' : 'lib').'unitsync.'.(MSWIN32 ? 'dll' : (DARWIN ? 'dylib' : 'so')),
};
(MSWIN32 ? eval { require Win32; require Win32::API; 1} : eval { require FFI::Platypus; 1})
or die $@;
my %UNITSYNC_FUNCTIONS;
while(local $_ = <DATA>) {
next unless(/^\s*EXPORT\(\s*([^\)]*[^\s\)])\s*\)\s*([^\(\s]+)\s*\(\s*((?:.*[^\s])?)\s*\)\s*;/);
my ($returnType,$funcName,$signature)=($1,$2,$3);
die "Duplicate function declaration \"$funcName\" in unitsync API source code" if(exists $UNITSYNC_FUNCTIONS{$funcName});
$UNITSYNC_FUNCTIONS{$funcName}={returnType => $returnType, signature => $signature};
}
close(DATA);
sub new {
my ($class,$libPath)=@_;
my $libName = defined $libPath ? catfile($libPath,UNITSYNC_LIB_NAME) : UNITSYNC_LIB_NAME;
my $self={libName => $libName,
api => {}};
$self->{ffi}=FFI::Platypus->new(lib => $libName) unless(MSWIN32);
bless($self,$class);
if(MSWIN32) {
# The unitsync lib has dependencies on Windows, so lib path must be added to PATH env var (or a chdir to lib path is needed...)
if(defined $libPath) {
$self->{originalPath}=$ENV{PATH};
$ENV{PATH}=$libPath.';'.$ENV{PATH};
}
if(my $dlHdl=Win32::API::LoadLibrary($libName)) {
Win32::API::FreeLibrary($dlHdl);
# Loading a symbol makes Win32::API cache the lib handle, so that the PATH env var dance is not needed for future calls
my $importError=$self->importFunc($UNITSYNC_FUNCTIONS{GetSpringVersion}{returnType},'GetSpringVersion',$UNITSYNC_FUNCTIONS{GetSpringVersion}{signature});
$ENV{PATH}=delete $self->{originalPath} if(defined $self->{originalPath});
die "Failed to import GetSpringVersion function from unitsync library \"$libName\" - $importError\n"
if($importError);
}else{
die "Failed to load unitsync library \"$libName\" - "._getLastWin32Error()."\n";
}
}elsif(my $dlHdl=FFI::Platypus::DL::dlopen($libName,FFI::Platypus::DL::RTLD_PLATYPUS_DEFAULT())) {
FFI::Platypus::DL::dlclose($dlHdl);
}else{
die "Failed to load unitsync library \"$libName\" - ".FFI::Platypus::DL::dlerror()."\n";
}
return $self;
}
sub preloadLibStdcpp {
croak 'preloadLibStdcpp() call invalid on Windows systems !' if(MSWIN32);
if(my $dlHdl=FFI::Platypus::DL::dlopen('libstdc++.so.6',FFI::Platypus::DL::RTLD_PLATYPUS_DEFAULT() | FFI::Platypus::DL::RTLD_GLOBAL())) {
FFI::Platypus::DL::dlclose($dlHdl);
return 1;
}
return 0;
}
sub _getLastWin32Error {
my $errorNb=Win32::GetLastError();
return 'unknown error' unless($errorNb);
my $errorMsg=Win32::FormatMessage($errorNb)//($^E=$errorNb);
$errorMsg=~s/\cM?\cJ$//;
return $errorMsg ? $errorMsg : 'unknown error';
}
sub _fixTypesForWin32Api {
$_[0]=~s/\bconst\s*//gi;
$_[0]=~s/\bbool\b/BOOL/g;
}
sub win32ImportFunc {
my ($self,$returnType,$funcName,$signature)=@_;
map {_fixTypesForWin32Api($_)} ($returnType,$signature);
my $r_win32ApiFunc=Win32::API->new($self->{libName},"$returnType $funcName($signature)")
or return _getLastWin32Error();
$self->{api}{$funcName}=sub { $r_win32ApiFunc->Call(@_) };
return undef;
}
sub _fixTypesForFfi {
my ($returnType,$signature)=@_;
$returnType=~s/\bconst\s*//i;
$returnType=~s/\bchar\*/string/i;
my @paramTypes=split(',',$signature);
foreach my $paramType (@paramTypes) {
if($paramType =~ /^\s*([^\s](?:.*[^\s])?)\s+[^\s]+\s*$/) {
$paramType=$1;
$paramType=~s/\bconst\s*//i;
$paramType=~s/\bchar\*/string/i unless($paramType =~ /unsigned/i);
}else{
die "Invalid type found in unitsync API source code: $paramType";
}
}
return ($returnType,\@paramTypes);
}
sub ffiImportFunc {
my ($self,$returnType,$funcName,$signature)=@_;
my $r_paramTypes;
($returnType,$r_paramTypes)=_fixTypesForFfi($returnType,$signature);
my $r_ffiFunc;
eval { $r_ffiFunc=$self->{ffi}->function($funcName,$r_paramTypes,$returnType) }
or return $@ || 'unknown error';
$self->{api}{$funcName}=$r_ffiFunc;
return undef;
}
sub win32HasSymbol { my ($self,$sym)=@_; return Win32::API::More->new($self->{libName},$sym,'V','V') }
sub ffiHasSymbol { my ($self,$sym)=@_; return $self->{ffi}->find_symbol($sym) }
*PerlUnitSync::importFunc = MSWIN32 ? \&win32ImportFunc : \&ffiImportFunc;
*PerlUnitSync::hasFunc = MSWIN32 ? \&win32HasSymbol : \&ffiHasSymbol;
sub DESTROY { $ENV{PATH}=delete $_[0]->{originalPath} if(defined $_[0]->{originalPath}) }
our $AUTOLOAD;
sub AUTOLOAD {
my $funcName=substr($AUTOLOAD,PACKAGE_PREFIX_LENGTH);
die "Unable to import unitsync function \"$funcName\" (function not found in API source code)\n"
unless(exists $UNITSYNC_FUNCTIONS{$funcName});
${PerlUnitSync::}{$funcName}=sub {
my $self=shift;
if(! exists $self->{api}{$funcName}) {
my $importError=$self->importFunc($UNITSYNC_FUNCTIONS{$funcName}{returnType},$funcName,$UNITSYNC_FUNCTIONS{$funcName}{signature});
die "Unable to import unitsync function \"$funcName\" from $self->{libName} ($importError)\n"
if($importError);
}
return $self->{api}{$funcName}->(@_);
};
return ${PerlUnitSync::}{$funcName}->(@_);
}
1;
#############################################################################
# https://github.com/spring/spring/raw/fca8e6/tools/unitsync/unitsync_api.h #
#############################################################################
__DATA__
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#ifndef _UNITSYNC_API_H
#define _UNITSYNC_API_H
#ifdef PLAIN_API_STRUCTURE
// This is useful when parsing/wrapping this file with preprocessor support.
// Do NOT use this when compiling!
#define EXPORT(type) type
#warning PLAIN_API_STRUCTURE is defined -> functions will NOT be properly exported!
#else
#include "unitsync.h"
#include "System/ExportDefines.h"
#endif
// from unitsync.cpp:
/** @addtogroup unitsync_api
@{ */
/**
* @brief Retrieves the next error in queue of errors and removes this error
* from the queue
* @return An error message, or NULL if there are no more errors in the queue
*
* Use this method to get a (short) description of errors that occurred in any
* other unitsync methods. Call this in a loop until it returns NULL to get all
* errors.
*
* The error messages may be varying in detail etc.; nothing is guaranteed about
* them, not even whether they have terminating newline or not.
*
* Example:
* @code
* const char* err;
* while ((err = GetNextError()) != NULL)
* printf("unitsync error: %s\n", err);
* @endcode
*/
EXPORT(const char* ) GetNextError();
/**
* @brief Retrieve the synced version of Spring
* this unitsync was compiled with.
*
* Returns a string specifying the synced part of the version of Spring used to
* build this library with.
*
* Before release 83:
* Release:
* The version will be of the format "Major.Minor".
* With Major=0.82 and Minor=6, the returned version would be "0.82.6".
* Development:
* They use the same format, but major ends with a +, for example "0.82+.5".
* Examples:
* - 0.78.0: 1st release of 0.78
* - 0.82.6: 7th release of 0.82
* - 0.82+.5: some test-version from after the 6th release of 0.82
* - 0.82+.0: some dev-version from after the 1st release of 0.82
* (on the main dev branch)
*
* After release 83:
* You may check for sync compatibility by using a string equality test with
* the return of this function.
* Release:
* Contains only the major version number, for example "83".
* You may combine this with the patch-set to get the full version,
* for example "83.2".
* Development:
* The full version, for example "83.0.1-13-g1234567 develop", and therefore
* it would not make sense to append the patch-set in such a case.
* Examples:
* - 83: any 83 release, for example 83.0 or 83.1
* this may only be on the the master or hotfix branch
* - 83.0.1-13-g1234567 develop: some dev-version after the 1st release of 83
* on the develop branch
*
* After release 106.0:
* The full version, for example "104.0.1-2155-gddd1321651 develop" or "105.0"
*/
EXPORT(const char* ) GetSpringVersion();
/**
* @brief Initialize the unitsync library
* @return Zero on error; non-zero on success
* @param isServer indicates whether the caller is hosting or joining a game
* @param id unused parameter TODO
*
* Call this function before calling any other function in unitsync.
* In case unitsync was already initialized, it is uninitialized and then
* reinitialized.
*
* Calling this function is currently the only way to clear the VFS of the
* files which are mapped into it. In other words, after using AddArchive() or
* AddAllArchives() you have to call Init when you want to remove the archives
* from the VFS and start with a clean state.
*
* The config handler will not be reset. It will however, be initialised if it
* was not before (with SetSpringConfigFile()).
*/
EXPORT(int ) Init(bool isServer, int id);
/**
* @brief Uninitialize the unitsync library
*
* also resets the config handler
*/
EXPORT(void ) UnInit();
/**
* @brief Get the main data directory that is used by unitsync and Spring
* @return NULL on error; the data directory path on success
*
* This is the data directory which is used to write logs, screen-shots, demos,
* etc.
*/
EXPORT(const char* ) GetWritableDataDirectory();
/**
* Returns the total number of readable data directories used by unitsync and
* the engine.
* @return negative integer (< 0) on error;
* the number of data directories available (>= 0) on success
*/
EXPORT(int ) GetDataDirectoryCount();
/**
* @brief Get the absolute path to i-th data directory
* @return NULL on error; the i-th data directory absolute path on success
*/
EXPORT(const char* ) GetDataDirectory(int index);
/**
* @brief Process units
*
* Must be called before GetUnitCount(), GetUnitName(), ...
*
* Before caling this function, you will first need to load a game's archives
* into the VFS using AddArchive() or AddAllArchives().
*
* @return always 0!
* @see ProcessUnitsNoChecksum
*/
EXPORT(int ) ProcessUnits();
/**
* @brief Get the number of units
* @return negative integer (< 0) on error;
* the number of units available (>= 0) on success
*
* Will return the number of units. Remember to call ProcessUnits() beforehand
* until it returns 0. As ProcessUnits() is called the number of processed
* units goes up, and so will the value returned by this function.
*
* Example:
* @code
* while (ProcessUnits() > 0) {}
* int numUnits = GetUnitCount();
* @endcode
*/
EXPORT(int ) GetUnitCount();
/**
* @brief Get the units internal mod name
* @param unit The units id number
* @return The units internal mod name, or NULL on error
*
* This function returns the units internal mod name. For example it would
* return 'armck' and not 'Arm Construction kbot'.
*/
EXPORT(const char* ) GetUnitName(int unit);
/**
* @brief Get the units human readable name
* @param unit The units id number
* @return The units human readable name or NULL on error
*
* This function returns the units human name. For example it would return
* 'Arm Construction kbot' and not 'armck'.
*/
EXPORT(const char* ) GetFullUnitName(int unit);
/**
* @brief Adds an archive to the VFS (Virtual File System)
*
* After this, the contents of the archive are available to other unitsync
* functions, for example:
* ProcessUnits(), OpenFileVFS(), ReadFileVFS(), FileSizeVFS(), etc.
*
* Do not forget to call RemoveAllArchives() before proceeding with other
* archives.
*/
EXPORT(void ) AddArchive(const char* archiveName);
/**
* @brief Adds an achive and all its dependencies to the VFS
* @see AddArchive
*/
EXPORT(void ) AddAllArchives(const char* rootArchiveName);
/**
* @brief Removes all archives from the VFS (Virtual File System)
*
* After this, the contents of the archives are not available to other unitsync
* functions anymore, for example:
* ProcessUnits(), OpenFileVFS(), ReadFileVFS(), FileSizeVFS(), etc.
*
* In a lobby-client, this may be used instead of Init() when switching mod
* archive.
*/
EXPORT(void ) RemoveAllArchives();
/**
* @brief Get checksum of an archive
* @return Zero on error; the checksum on success
*
* This checksum depends only on the contents from the archive itself, and not
* on the contents from dependencies of this archive (if any).
*/
EXPORT(unsigned int) GetArchiveChecksum(const char* archiveName);
/**
* @brief Gets the real path to the archive
* @return NULL on error; a path to the archive on success
*/
EXPORT(const char* ) GetArchivePath(const char* archiveName);
/**
* @brief Get the number of maps available
* @return negative integer (< 0) on error;
* the number of maps available (>= 0) on success
*
* Call this before any of the map functions which take a map index as
* parameter.
* This function actually performs a relatively costly enumeration of all maps,
* so you should resist from calling it repeatedly in a loop. Rather use:
* @code
* int map_count = GetMapCount();
* for (int index = 0; index < map_count; ++index) {
* printf("map name: %s\n", GetMapName(index));
* }
* @endcode
* Then:
* @code
* for (int index = 0; index < GetMapCount(); ++index) { ... }
* @endcode
*/
EXPORT(int ) GetMapCount();
/**
* @brief Retrieves the number of info items available for a given Map
* @param index Map index/id
* @return negative integer (< 0) on error;
* the number of info items available (>= 0) on success
* @see GetMapCount
* @see GetInfoKey
*
* Be sure to call GetMapCount() prior to using this function.
*/
EXPORT(int ) GetMapInfoCount(int index);
/**
* @brief Get the name of a map
* @return NULL on error; the name of the map (e.g. "SmallDivide") on success
*/
EXPORT(const char* ) GetMapName(int index);
/**
* @brief Get the file-name (+ VFS-path) of a map
* @return NULL on error; the file-name of the map (e.g. "maps/SmallDivide.smf")
* on success
*/
EXPORT(const char* ) GetMapFileName(int index);
/**
* @brief return the map's minimum height
* @param mapName name of the map, e.g. "SmallDivide"
* @return 0.0f on error; the map's minimum height on success
*
* Together with maxHeight, this determines the
* range of the map's height values in-game. The
* conversion formula for any raw 16-bit height
* datum <code>h</code> is
* <code>minHeight + (h * (maxHeight - minHeight) / 65536.0f)</code>
*/
EXPORT(float ) GetMapMinHeight(const char* mapName);
/**
* @brief return the map's maximum height
* @param mapName name of the map, e.g. "SmallDivide"
* @return 0.0f on error; the map's maximum height on success
*
* Together with minHeight, this determines the
* range of the map's height values in-game. See
* GetMapMinHeight() for the conversion formula.
*/
EXPORT(float ) GetMapMaxHeight(const char* mapName);
/**
* @brief Retrieves the number of archives a map requires
* @param mapName name of the map, e.g. "SmallDivide"
* @return negative integer (< 0) on error;
* the number of archives (>= 0) on success
*
* Must be called before GetMapArchiveName()
*/
EXPORT(int ) GetMapArchiveCount(const char* mapName);
/**
* @brief Retrieves an archive a map requires
* @param index the index of the archive
* @return NULL on error; the name of the archive on success
*/
EXPORT(const char* ) GetMapArchiveName(int index);
/**
* @brief Get map checksum given a map index
* @param index the index of the map
* @return Zero on error; the checksum on success
*
* This checksum depends on Spring internals, and as such should not be expected
* to remain stable between releases.
*
* (It is meant to check sync between clients in lobby, for example.)
*/
EXPORT(unsigned int) GetMapChecksum(int index);
/**
* @brief Get map checksum given a map name
* @param mapName name of the map, e.g. "SmallDivide"
* @return Zero on error; the checksum on success
* @see GetMapChecksum
*/
EXPORT(unsigned int) GetMapChecksumFromName(const char* mapName);
/**
* @brief Retrieves a minimap image for a map.
* @param fileName The name of the map, including extension.
* @param mipLevel Which mip-level of the minimap to extract from the file.
* Set mip-level to 0 to get the largest, 1024x1024 minimap. Each increment
* divides the width and height by 2. The maximum mip-level is 8, resulting in a
* 4x4 image.
* @return A pointer to a static memory area containing the minimap as a 16 bit
* packed RGB-565 (MSB to LSB: 5 bits red, 6 bits green, 5 bits blue) linear
* bitmap on success; NULL on error.
*
* An example usage would be GetMinimap("SmallDivide", 2).
* This would return a 16 bit packed RGB-565 256x256 (= 1024/2^2) bitmap.
*/
EXPORT(unsigned short*) GetMinimap(const char* fileName, int mipLevel);
/**
* @brief Retrieves dimensions of infomap for a map.
* @param mapName The name of the map, e.g. "SmallDivide".
* @param name Of which infomap to retrieve the dimensions.
* @param width This is set to the width of the infomap, or 0 on error.
* @param height This is set to the height of the infomap, or 0 on error.
* @return negative integer (< 0) on error;
* the infomap's size (>= 0) on success
* @see GetInfoMap
*/
EXPORT(int ) GetInfoMapSize(const char* mapName, const char* name, int* width, int* height);
/**
* @brief Retrieves infomap data of a map.
* @param mapName The name of the map, e.g. "SmallDivide".
* @param name Which infomap to extract from the file.
* @param data Pointer to a memory location with enough room to hold the
* infomap data.
* @param typeHint One of bm_grayscale_8 (or 1) and bm_grayscale_16 (or 2).
* @return negative integer (< 0) on error;
* the infomap's size (> 0) on success
* An error could indicate that the map was not found, the infomap was not found
* or typeHint could not be honored.
*
* This function extracts an infomap from a map. This can currently be one of:
* "height", "metal", "grass", "type". The heightmap is natively in 16 bits per
* pixel, the others are in 8 bits pixel. Using typeHint one can give a hint to
* this function to convert from one format to another. Currently only the
* conversion from 16 bpp to 8 bpp is implemented.
*/
EXPORT(int ) GetInfoMap(const char* mapName, const char* name, unsigned char* data, int typeHint);
/**
* @brief Retrieves the number of Skirmish AIs available
* @return negative integer (< 0) on error;
* the number of Skirmish AIs available (>= 0) on success
* @see GetMapCount
*/
EXPORT(int ) GetSkirmishAICount();
/**
* @brief Retrieves the number of info items available for a given Skirmish AI
* @param index Skirmish AI index/id
* @return negative integer (< 0) on error;
* the number of info items available (>= 0) on success
* @see GetSkirmishAICount
*
* Be sure to call GetSkirmishAICount() prior to using this function.
*/
EXPORT(int ) GetSkirmishAIInfoCount(int index);
/**
* @brief Retrieves an info item's key
* @param index info item index/id
* @return NULL on error; the info item's key on success
* @see GetSkirmishAIInfoCount
*
* The key of an option is either one defined as SKIRMISH_AI_PROPERTY_* in
* ExternalAI/Interface/SSkirmishAILibrary.h, or a custom one.
* Be sure to call GetSkirmishAIInfoCount() prior to using this function.
*/
EXPORT(const char* ) GetInfoKey(int index);
/**
* @brief Retrieves an info item's value type
* @param index info item index/id
* @return NULL on error; the info item's value type on success,
* which will be one of:
* "string", "integer", "float", "bool"
* @see GetSkirmishAIInfoCount
* @see GetInfoValueString
* @see GetInfoValueInteger
* @see GetInfoValueFloat
* @see GetInfoValueBool
*
* Be sure to call GetSkirmishAIInfoCount() prior to using this function.
*/
EXPORT(const char* ) GetInfoType(int index);
/**
* @brief Retrieves an info item's value of type string
* @param index info item index/id
* @return NULL on error; the info item's value on success
* @see GetSkirmishAIInfoCount
* @see GetInfoType
*
* Be sure to call GetSkirmishAIInfoCount() prior to using this function.
*/
EXPORT(const char* ) GetInfoValueString(int index);
/**
* @brief Retrieves an info item's value of type integer
* @param index info item index/id
* @return the info item's value; -1 might imply a value of -1 or an error
* @see GetSkirmishAIInfoCount
* @see GetInfoType
*
* Be sure to call GetSkirmishAIInfoCount() prior to using this function.
*/
EXPORT(int ) GetInfoValueInteger(int index);
/**
* @brief Retrieves an info item's value of type float
* @param index info item index/id
* @return the info item's value; -1.0f might imply a value of -1.0f or an error
* @see GetSkirmishAIInfoCount
* @see GetInfoType
*
* Be sure to call GetSkirmishAIInfoCount() prior to using this function.
*/
EXPORT(float ) GetInfoValueFloat(int index);
/**
* @brief Retrieves an info item's value of type bool
* @param index info item index/id
* @return the info item's value; false might imply the value false or an error
* @see GetSkirmishAIInfoCount
* @see GetInfoType
*
* Be sure to call GetSkirmishAIInfoCount() prior to using this function.
*/
EXPORT(bool ) GetInfoValueBool(int index);
/**
* @brief Retrieves an info item's description
* @param index info item index/id
* @return NULL on error; the info item's description on success
* @see GetSkirmishAIInfoCount
*
* Be sure to call GetSkirmishAIInfoCount() prior to using this function.
*/
EXPORT(const char* ) GetInfoDescription(int index);
/**
* @brief Retrieves the number of options available for a given Skirmish AI
* @param index Skirmish AI index/id
* @return negative integer (< 0) on error;
* the number of Skirmish AI options available (>= 0) on success
* @see GetSkirmishAICount
* @see GetOptionKey
* @see GetOptionName
* @see GetOptionDesc
* @see GetOptionType
*
* Be sure to call GetSkirmishAICount() prior to using this function.
*/
EXPORT(int ) GetSkirmishAIOptionCount(int index);
/**
* @brief Retrieves the number of mods available
* @return negative integer (< 0) on error;
* the number of mods available (>= 0) on success
* @see GetMapCount
*/
EXPORT(int ) GetPrimaryModCount();
/**
* @brief Retrieves the number of info items available for this mod
* @param index The mods index/id
* @return negative integer (< 0) on error;
* the number of info items available (>= 0) on success
* @see GetPrimaryModCount
* @see GetInfoKey
* @see GetInfoType
* @see GetInfoDescription
*
* Be sure you have made a call to GetPrimaryModCount() prior to using this.
*/
EXPORT(int ) GetPrimaryModInfoCount(int index);
/**
* @brief Retrieves the mod's first/primary archive
* @param index The mods index/id
* @return NULL on error; The mods primary archive on success
*
* Returns the name of the primary archive of the mod.
* Be sure you have made a call to GetPrimaryModCount() prior to using this.
*/
EXPORT(const char* ) GetPrimaryModArchive(int index);
/**
* @brief Retrieves the number of archives a mod requires
* @param index The index of the mod
* @return negative integer (< 0) on error;
* the number of archives this mod depends on (>= 0) on success
*
* This is used to get the entire list of archives that a mod requires.
* Call GetPrimaryModArchiveCount() with selected mod first to get number of
* archives, and then use GetPrimaryModArchiveList() for 0 to count-1 to get the
* name of each archive. In code:
* @code
* int count = GetPrimaryModArchiveCount(mod_index);
* for (int archive = 0; archive < count; ++archive) {
* printf("primary mod archive: %s\n", GetPrimaryModArchiveList(archive));
* }
* @endcode
*/
EXPORT(int ) GetPrimaryModArchiveCount(int index);
/**
* @brief Retrieves the name of the current mod's archive.
* @param archive The archive's index/id.
* @return NULL on error; the name of the archive on success
* @see GetPrimaryModArchiveCount
*/
EXPORT(const char* ) GetPrimaryModArchiveList(int archive);
/**
* @brief The reverse of GetPrimaryModName()
* @param name The name of the mod
* @return negative integer (< 0) on error
* (game was not found or GetPrimaryModCount() was not called yet);
* the index of the mod (>= 0) on success
*/
EXPORT(int ) GetPrimaryModIndex(const char* name);
/**
* @brief Get checksum of mod
* @param index The mods index/id
* @return Zero on error; the checksum on success.
* @see GetMapChecksum
*/
EXPORT(unsigned int) GetPrimaryModChecksum(int index);
/**
* @brief Get checksum of mod given the mod's name
* @param name The name of the mod
* @return Zero on error; the checksum on success.
* @see GetMapChecksum
*/
EXPORT(unsigned int) GetPrimaryModChecksumFromName(const char* name);
/**
* @brief Retrieve the number of available sides
* @return negative integer (< 0) on error;
* the number of sides (>= 0) on success
*
* This function parses the mod's side data, and returns the number of sides
* available. Be sure to map the mod into the VFS using AddArchive() or
* AddAllArchives() prior to using this function.
*/
EXPORT(int ) GetSideCount();
/**
* @brief Retrieve a side's name
* @return NULL on error; the side's name on success
*
* Be sure you have made a call to GetSideCount() prior to using this.
*/
EXPORT(const char* ) GetSideName(int side);
/**
* @brief Retrieve a side's default starting unit
* @return NULL on error; the side's starting unit name on success
*
* Be sure you have made a call to GetSideCount() prior to using this.
*/
EXPORT(const char* ) GetSideStartUnit(int side);
/**
* @brief Retrieve the number of map options available
* @param mapName the name of the map, e.g. "SmallDivide"
* @return negative integer (< 0) on error;
* the number of map options available (>= 0) on success
* @see GetOptionKey
* @see GetOptionName
* @see GetOptionDesc
* @see GetOptionType
*/
EXPORT(int ) GetMapOptionCount(const char* mapName);
/**
* @brief Retrieve the number of mod options available
* @return negative integer (< 0) on error;
* the number of mod options available (>= 0) on success
* @see GetOptionKey
* @see GetOptionName
* @see GetOptionDesc
* @see GetOptionType
*
* Be sure to map the mod into the VFS using AddArchive() or AddAllArchives()
* prior to using this function.
*/
EXPORT(int ) GetModOptionCount();
/**
* @brief Returns the number of options available in a specific option file
* @param fileName the VFS path to a Lua file containing an options table
* @return negative integer (< 0) on error;
* the number of options available (>= 0) on success
* @see GetOptionKey
* @see GetOptionName
* @see GetOptionDesc
* @see GetOptionType
*/
EXPORT(int ) GetCustomOptionCount(const char* fileName);
/**
* @brief Retrieve an option's key
* @param optIndex option index/id
* @return NULL on error; the option's key on success
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*
* For mods, maps or Skimrish AIs, the key of an option is the name it should be
* given in the start script (section [MODOPTIONS], [MAPOPTIONS] or
* [AI/OPTIONS]).
*/
EXPORT(const char* ) GetOptionKey(int optIndex);
/**
* @brief Retrieve an option's scope
* @param optIndex option index/id
* @return NULL on error; the option's scope on success, one of:
* "global" (default), "player", "team", "allyteam"
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*/
EXPORT(const char* ) GetOptionScope(int optIndex);
/**
* @brief Retrieve an option's name
* @param optIndex option index/id
* @return NULL on error; the option's user visible name on success
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*/
EXPORT(const char* ) GetOptionName(int optIndex);
/**
* @brief Retrieve an option's section
* @param optIndex option index/id
* @return NULL on error; the option's section name on success
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*/
EXPORT(const char* ) GetOptionSection(int optIndex);
/**
* @brief Retrieve an option's description
* @param optIndex option index/id
* @return NULL on error; the option's description on success
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*/
EXPORT(const char* ) GetOptionDesc(int optIndex);
/**
* @brief Retrieve an option's type
* @param optIndex option index/id
* @return negative integer (< 0) or opt_error (0) on error;
* the option's type on success
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*/
EXPORT(int ) GetOptionType(int optIndex);
/**
* @brief Retrieve an opt_bool option's default value
* @param optIndex option index/id
* @return negative integer (< 0) on error;
* the option's default value (0 or 1) on success
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*/
EXPORT(int ) GetOptionBoolDef(int optIndex);
/**
* @brief Retrieve an opt_number option's default value
* @param optIndex option index/id
* @return the option's default value;
* -1.0f might imply a value of -1.0f or an error
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*/
EXPORT(float ) GetOptionNumberDef(int optIndex);
/**
* @brief Retrieve an opt_number option's minimum value
* @param optIndex option index/id
* @return -1.0e30 on error; the option's minimum value on success
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*/
EXPORT(float ) GetOptionNumberMin(int optIndex);
/**
* @brief Retrieve an opt_number option's maximum value
* @param optIndex option index/id
* @return +1.0e30 on error; the option's maximum value on success
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*/
EXPORT(float ) GetOptionNumberMax(int optIndex);
/**
* @brief Retrieve an opt_number option's step value
* @param optIndex option index/id
* @return the option's step value;
* -1.0f might imply a value of -1.0f or an error
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*/
EXPORT(float ) GetOptionNumberStep(int optIndex);
/**
* @brief Retrieve an opt_string option's default value
* @param optIndex option index/id
* @return NULL on error; the option's default value on success
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*/
EXPORT(const char* ) GetOptionStringDef(int optIndex);
/**
* @brief Retrieve an opt_string option's maximum length
* @param optIndex option index/id
* @return negative integer (< 0) on error;
* the option's maximum length (>= 0) on success
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*/
EXPORT(int ) GetOptionStringMaxLen(int optIndex);
/**
* @brief Retrieve an opt_list option's number of available items
* @param optIndex option index/id
* @return negative integer (< 0) on error;
* the option's number of available items (>= 0) on success
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*/
EXPORT(int ) GetOptionListCount(int optIndex);
/**
* @brief Retrieve an opt_list option's default value
* @param optIndex option index/id
* @return NULL on error; the option's default value (list item key) on success
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*/
EXPORT(const char* ) GetOptionListDef(int optIndex);
/**
* @brief Retrieve an opt_list option item's key
* @param optIndex option index/id
* @param itemIndex list item index/id
* @return NULL on error; the option item's key (list item key) on success
*
* Do not use this before having called Get*OptionCount().
* @see GetMapOptionCount
* @see GetModOptionCount
* @see GetSkirmishAIOptionCount
* @see GetCustomOptionCount
*/
EXPORT(const char* ) GetOptionListItemKey(int optIndex, int itemIndex);
/**