open-tibia-tools 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +29 -0
  2. package/effectFramesGenerator.html +42 -0
  3. package/effectFramesGenerator.ts +95 -0
  4. package/itemImageFramesGenerator.html +45 -0
  5. package/itemImageFramesGenerator.ts +140 -0
  6. package/itemImageGenerator.html +40 -0
  7. package/itemImageGenerator.ts +161 -0
  8. package/missileFramesGenerator.html +42 -0
  9. package/missileFramesGenerator.ts +95 -0
  10. package/otbEditor.html +21 -0
  11. package/otbEditor.ts +106 -0
  12. package/outfitImageGenerator.html +38 -0
  13. package/outfitImageGenerator.ts +109 -0
  14. package/outfitImagePhpGeneratorCode.ts +19 -0
  15. package/package.json +28 -0
  16. package/tests.html +29 -0
  17. package/tests.ts +218 -0
  18. package/tools/colored-outfit-images-generator/README.md +7 -0
  19. package/tools/colored-outfit-images-generator/abuse_warning.png +0 -0
  20. package/tools/colored-outfit-images-generator/animoutfit.php +103 -0
  21. package/tools/colored-outfit-images-generator/cacheGenerator.php +40 -0
  22. package/tools/colored-outfit-images-generator/config.php +25 -0
  23. package/tools/colored-outfit-images-generator/filesAsJson.php +22 -0
  24. package/tools/colored-outfit-images-generator/index.php +21 -0
  25. package/tools/colored-outfit-images-generator/libs/gifCreator.php +343 -0
  26. package/tools/colored-outfit-images-generator/libs/outfitter.php +312 -0
  27. package/tools/colored-outfit-images-generator/outfit.php +77 -0
  28. package/tools/colored-outfit-images-generator/release.php +40 -0
  29. package/tools/item-image-frames-to-animated-gif-converter/1-10/1.gif +0 -0
  30. package/tools/item-image-frames-to-animated-gif-converter/1-10/1.png +0 -0
  31. package/tools/item-image-frames-to-animated-gif-converter/1-10/10.gif +0 -0
  32. package/tools/item-image-frames-to-animated-gif-converter/1-10/10.png +0 -0
  33. package/tools/item-image-frames-to-animated-gif-converter/1-10/2.gif +0 -0
  34. package/tools/item-image-frames-to-animated-gif-converter/1-10/2.png +0 -0
  35. package/tools/item-image-frames-to-animated-gif-converter/1-10/3.gif +0 -0
  36. package/tools/item-image-frames-to-animated-gif-converter/1-10/3.png +0 -0
  37. package/tools/item-image-frames-to-animated-gif-converter/1-10/4.gif +0 -0
  38. package/tools/item-image-frames-to-animated-gif-converter/1-10/4.png +0 -0
  39. package/tools/item-image-frames-to-animated-gif-converter/1-10/5.gif +0 -0
  40. package/tools/item-image-frames-to-animated-gif-converter/1-10/5.png +0 -0
  41. package/tools/item-image-frames-to-animated-gif-converter/1-10/6.gif +0 -0
  42. package/tools/item-image-frames-to-animated-gif-converter/1-10/6.png +0 -0
  43. package/tools/item-image-frames-to-animated-gif-converter/1-10/7.gif +0 -0
  44. package/tools/item-image-frames-to-animated-gif-converter/1-10/7.png +0 -0
  45. package/tools/item-image-frames-to-animated-gif-converter/1-10/8.gif +0 -0
  46. package/tools/item-image-frames-to-animated-gif-converter/1-10/8.png +0 -0
  47. package/tools/item-image-frames-to-animated-gif-converter/1-10/9.gif +0 -0
  48. package/tools/item-image-frames-to-animated-gif-converter/1-10/9.png +0 -0
  49. package/tools/item-image-frames-to-animated-gif-converter/README.md +20 -0
  50. package/tools/item-image-frames-to-animated-gif-converter/cli_convert.php +42 -0
  51. package/tools/item-image-frames-to-animated-gif-converter/generated-zip-archives/.gitignore +3 -0
  52. package/tools/item-image-frames-to-animated-gif-converter/generated-zip-archives/index.html +1 -0
  53. package/tools/item-image-frames-to-animated-gif-converter/index.php +97 -0
  54. package/tools/item-image-frames-to-animated-gif-converter/lib/abstractPngConverterAnimation.php +87 -0
  55. package/tools/item-image-frames-to-animated-gif-converter/lib/apngCreator.php +247 -0
  56. package/tools/item-image-frames-to-animated-gif-converter/lib/converterPngToApngAnimation.php +93 -0
  57. package/tools/item-image-frames-to-animated-gif-converter/lib/converterPngToGifAnimation.php +90 -0
  58. package/tools/item-image-frames-to-animated-gif-converter/lib/gifCreator.php +339 -0
  59. package/tsconfig.json +12 -0
  60. package/webpack.config.js +53 -0
  61. package/websiteImageGeneratorBase.ts +156 -0
@@ -0,0 +1,343 @@
1
+ <?php
2
+
3
+ /**
4
+ * Create an animated GIF from multiple images
5
+ *
6
+ * @update by gesior, php 8.0 compatibility
7
+ *
8
+ * @version 1.0
9
+ * @link https://github.com/Sybio/GifCreator
10
+ * @author Sybio (Clément Guillemain / @Sybio01)
11
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
12
+ * @copyright Clément Guillemain
13
+ */
14
+ class GifCreator
15
+ {
16
+ /**
17
+ * @var string The gif string source (old: this->GIF)
18
+ */
19
+ private $gif;
20
+
21
+ /**
22
+ * @var string Encoder version (old: this->VER)
23
+ */
24
+ private $version;
25
+
26
+ /**
27
+ * @var boolean Check the image is build or not (old: this->IMG)
28
+ */
29
+ private $imgBuilt;
30
+
31
+ /**
32
+ * @var array Frames string sources (old: this->BUF)
33
+ */
34
+ private $frameSources;
35
+
36
+ /**
37
+ * @var integer Gif loop (old: this->LOP)
38
+ */
39
+ private $loop;
40
+
41
+ /**
42
+ * @var integer Gif dis (old: this->DIS)
43
+ */
44
+ private $dis;
45
+
46
+ /**
47
+ * @var integer Gif color (old: this->COL)
48
+ */
49
+ private $colour;
50
+
51
+ /**
52
+ * @var array (old: this->ERR)
53
+ */
54
+ private $errors;
55
+
56
+ // Methods
57
+ // ===================================================================================
58
+
59
+ /**
60
+ * Constructor
61
+ */
62
+ public function __construct()
63
+ {
64
+ $this->reset();
65
+
66
+ // Static data
67
+ $this->version = 'GifCreator: Under development';
68
+ $this->errors = array(
69
+ 'ERR00' => 'Does not supported function for only one image.',
70
+ 'ERR01' => 'Source is not a GIF image.',
71
+ 'ERR02' => 'You have to give resource image variables, image URL or image binary sources in $frames array.',
72
+ 'ERR03' => 'Does not make animation from animated GIF source.',
73
+ );
74
+ }
75
+
76
+ /**
77
+ * Create the GIF string (old: GIFEncoder)
78
+ *
79
+ * @param array $frames An array of frame: can be file paths, resource image variables, binary sources or image URLs
80
+ * @param array $durations An array containing the duration of each frame
81
+ * @param integer $loop Number of GIF loops before stopping animation (Set 0 to get an infinite loop)
82
+ *
83
+ * @return string The GIF string source
84
+ */
85
+ public function create($frames = array(), $durations = array(), $loop = 0)
86
+ {
87
+ if (!is_array($frames) && !is_array($durations)) {
88
+ throw new \Exception($this->version . ': ' . $this->errors['ERR00']);
89
+ }
90
+
91
+ $this->loop = ($loop > -1) ? $loop : 0;
92
+ $this->dis = 2;
93
+
94
+ for ($i = 0; $i < count($frames); $i++) {
95
+ if ($frames[$i] instanceof GdImage || is_resource($frames[$i])) { // Resource var
96
+
97
+ $resourceImg = $frames[$i];
98
+
99
+ ob_start();
100
+ imagegif($frames[$i]);
101
+ $this->frameSources[] = ob_get_contents();
102
+ ob_end_clean();
103
+ } elseif (is_string($frames[$i])) { // File path or URL or Binary source code
104
+
105
+ if (file_exists($frames[$i]) || filter_var($frames[$i], FILTER_VALIDATE_URL)) { // File path
106
+
107
+ $frames[$i] = file_get_contents($frames[$i]);
108
+ }
109
+
110
+ $resourceImg = imagecreatefromstring($frames[$i]);
111
+
112
+ ob_start();
113
+ imagegif($resourceImg);
114
+ $this->frameSources[] = ob_get_contents();
115
+ ob_end_clean();
116
+ } else { // Fail
117
+
118
+ throw new \Exception($this->version . ': ' . $this->errors['ERR02']);
119
+ }
120
+
121
+ if ($i == 0) {
122
+ $transparentIndex = imagecolortransparent($resourceImg);
123
+ if ($transparentIndex >= 0 && (imageistruecolor($resourceImg) || $transparentIndex < imagecolorstotal($resourceImg))) {
124
+ $colors = imagecolorsforindex($resourceImg, $transparentIndex);
125
+ $colour = ($colors['red'] << 16) | ($colors['green'] << 8) | $colors['blue'];
126
+ }
127
+ }
128
+
129
+ if (substr($this->frameSources[$i], 0, 6) != 'GIF87a' && substr(
130
+ $this->frameSources[$i],
131
+ 0,
132
+ 6
133
+ ) != 'GIF89a') {
134
+ throw new \Exception($this->version . ': ' . $i . ' ' . $this->errors['ERR01']);
135
+ }
136
+
137
+ for ($j = (13 + 3 * (2 << (ord($this->frameSources[$i] [10]) & 0x07))), $k = true; $k; $j++) {
138
+ switch ($this->frameSources[$i] [$j]) {
139
+ case '!':
140
+
141
+ if ((substr($this->frameSources[$i], ($j + 3), 8)) == 'NETSCAPE') {
142
+ throw new \Exception(
143
+ $this->version . ': ' . $this->errors['ERR03'] . ' (' . ($i + 1) . ' source).'
144
+ );
145
+ }
146
+
147
+ break;
148
+
149
+ case ';':
150
+
151
+ $k = false;
152
+ break;
153
+ }
154
+ }
155
+
156
+ unset($resourceImg);
157
+ }
158
+
159
+ if (isset($colour)) {
160
+ $this->colour = $colour;
161
+ } else {
162
+ $red = $green = $blue = 0;
163
+ $this->colour = ($red > -1 && $green > -1 && $blue > -1) ? ($red | ($green << 8) | ($blue << 16)) : -1;
164
+ }
165
+
166
+ $this->gifAddHeader();
167
+
168
+ for ($i = 0; $i < count($this->frameSources); $i++) {
169
+ $this->addGifFrames($i, $durations[$i]);
170
+ }
171
+
172
+ $this->gifAddFooter();
173
+
174
+ return $this->gif;
175
+ }
176
+
177
+ // Internals
178
+ // ===================================================================================
179
+
180
+ /**
181
+ * Add the header gif string in its source (old: GIFAddHeader)
182
+ */
183
+ public function gifAddHeader()
184
+ {
185
+ $cmap = 0;
186
+
187
+ if (ord($this->frameSources[0] [10]) & 0x80) {
188
+ $cmap = 3 * (2 << (ord($this->frameSources[0] [10]) & 0x07));
189
+
190
+ $this->gif .= substr($this->frameSources[0], 6, 7);
191
+ $this->gif .= substr($this->frameSources[0], 13, $cmap);
192
+ $this->gif .= "!\377\13NETSCAPE2.0\3\1" . $this->encodeAsciiToChar($this->loop) . "\0";
193
+ }
194
+ }
195
+
196
+ /**
197
+ * Add the frame sources to the GIF string (old: GIFAddFrames)
198
+ *
199
+ * @param integer $i
200
+ * @param integer $d
201
+ */
202
+ public function addGifFrames($i, $d)
203
+ {
204
+ $Locals_str = 13 + 3 * (2 << (ord($this->frameSources[$i] [10]) & 0x07));
205
+
206
+ $Locals_end = strlen($this->frameSources[$i]) - $Locals_str - 1;
207
+ $Locals_tmp = substr($this->frameSources[$i], $Locals_str, $Locals_end);
208
+
209
+ $Global_len = 2 << (ord($this->frameSources[0] [10]) & 0x07);
210
+ $Locals_len = 2 << (ord($this->frameSources[$i] [10]) & 0x07);
211
+
212
+ $Global_rgb = substr($this->frameSources[0], 13, 3 * (2 << (ord($this->frameSources[0] [10]) & 0x07)));
213
+ $Locals_rgb = substr($this->frameSources[$i], 13, 3 * (2 << (ord($this->frameSources[$i] [10]) & 0x07)));
214
+
215
+ $Locals_ext = "!\xF9\x04" . chr(($this->dis << 2) + 0) . chr(($d >> 0) & 0xFF) . chr(
216
+ ($d >> 8) & 0xFF
217
+ ) . "\x0\x0";
218
+
219
+ if ($this->colour > -1 && ord($this->frameSources[$i] [10]) & 0x80) {
220
+ for ($j = 0; $j < (2 << (ord($this->frameSources[$i] [10]) & 0x07)); $j++) {
221
+ if (ord($Locals_rgb [3 * $j + 0]) == (($this->colour >> 16) & 0xFF) &&
222
+ ord($Locals_rgb [3 * $j + 1]) == (($this->colour >> 8) & 0xFF) &&
223
+ ord($Locals_rgb [3 * $j + 2]) == (($this->colour >> 0) & 0xFF)
224
+ ) {
225
+ $Locals_ext = "!\xF9\x04" . chr(($this->dis << 2) + 1) . chr(($d >> 0) & 0xFF) . chr(
226
+ ($d >> 8) & 0xFF
227
+ ) . chr($j) . "\x0";
228
+ break;
229
+ }
230
+ }
231
+ }
232
+
233
+ switch ($Locals_tmp [0]) {
234
+ case '!':
235
+
236
+ $Locals_img = substr($Locals_tmp, 8, 10);
237
+ $Locals_tmp = substr($Locals_tmp, 18, strlen($Locals_tmp) - 18);
238
+
239
+ break;
240
+
241
+ case ',':
242
+
243
+ $Locals_img = substr($Locals_tmp, 0, 10);
244
+ $Locals_tmp = substr($Locals_tmp, 10, strlen($Locals_tmp) - 10);
245
+
246
+ break;
247
+ }
248
+
249
+ if (ord($this->frameSources[$i] [10]) & 0x80 && $this->imgBuilt) {
250
+ if ($Global_len == $Locals_len) {
251
+ if ($this->gifBlockCompare($Global_rgb, $Locals_rgb, $Global_len)) {
252
+ $this->gif .= $Locals_ext . $Locals_img . $Locals_tmp;
253
+ } else {
254
+ $byte = ord($Locals_img [9]);
255
+ $byte |= 0x80;
256
+ $byte &= 0xF8;
257
+ $byte |= (ord($this->frameSources[0] [10]) & 0x07);
258
+ $Locals_img [9] = chr($byte);
259
+ $this->gif .= $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp;
260
+ }
261
+ } else {
262
+ $byte = ord($Locals_img [9]);
263
+ $byte |= 0x80;
264
+ $byte &= 0xF8;
265
+ $byte |= (ord($this->frameSources[$i] [10]) & 0x07);
266
+ $Locals_img [9] = chr($byte);
267
+ $this->gif .= $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp;
268
+ }
269
+ } else {
270
+ $this->gif .= $Locals_ext . $Locals_img . $Locals_tmp;
271
+ }
272
+
273
+ $this->imgBuilt = true;
274
+ }
275
+
276
+ /**
277
+ * Add the gif string footer char (old: GIFAddFooter)
278
+ */
279
+ public function gifAddFooter()
280
+ {
281
+ $this->gif .= ';';
282
+ }
283
+
284
+ /**
285
+ * Compare two block and return the version (old: GIFBlockCompare)
286
+ *
287
+ * @param string $globalBlock
288
+ * @param string $localBlock
289
+ * @param integer $length
290
+ *
291
+ * @return integer
292
+ */
293
+ public function gifBlockCompare($globalBlock, $localBlock, $length)
294
+ {
295
+ for ($i = 0; $i < $length; $i++) {
296
+ if ($globalBlock [3 * $i + 0] != $localBlock [3 * $i + 0] ||
297
+ $globalBlock [3 * $i + 1] != $localBlock [3 * $i + 1] ||
298
+ $globalBlock [3 * $i + 2] != $localBlock [3 * $i + 2]) {
299
+ return 0;
300
+ }
301
+ }
302
+
303
+ return 1;
304
+ }
305
+
306
+ /**
307
+ * Encode an ASCII char into a string char (old: GIFWord)
308
+ *
309
+ * $param integer $char ASCII char
310
+ *
311
+ * @return string
312
+ */
313
+ public function encodeAsciiToChar($char)
314
+ {
315
+ return (chr($char & 0xFF) . chr(($char >> 8) & 0xFF));
316
+ }
317
+
318
+ /**
319
+ * Reset and clean the current object
320
+ */
321
+ public function reset()
322
+ {
323
+ $this->frameSources;
324
+ $this->gif = 'GIF89a'; // the GIF header
325
+ $this->imgBuilt = false;
326
+ $this->loop = 0;
327
+ $this->dis = 2;
328
+ $this->colour = -1;
329
+ }
330
+
331
+ // Getter / Setter
332
+ // ===================================================================================
333
+
334
+ /**
335
+ * Get the final GIF image string (old: GetAnimation)
336
+ *
337
+ * @return string
338
+ */
339
+ public function getGif()
340
+ {
341
+ return $this->gif;
342
+ }
343
+ }
@@ -0,0 +1,312 @@
1
+ <?php
2
+ /**
3
+ * @author Kamil Karkus <kaker@wp.eu>
4
+ * @author Gesior.pl <phoowned@wp.pl>
5
+ * @copyright Copyright (c) 2012, Kamil Karkus
6
+ * @version 6 - fixed background transparency in GIFs
7
+ */
8
+
9
+ class Outfitter {
10
+ protected static $instance = null;
11
+ protected static $outfitColors = array(
12
+ 0xFFFFFF, 0xFFD4BF, 0xFFE9BF, 0xFFFFBF, 0xE9FFBF, 0xD4FFBF,
13
+ 0xBFFFBF, 0xBFFFD4, 0xBFFFE9, 0xBFFFFF, 0xBFE9FF, 0xBFD4FF,
14
+ 0xBFBFFF, 0xD4BFFF, 0xE9BFFF, 0xFFBFFF, 0xFFBFE9, 0xFFBFD4,
15
+ 0xFFBFBF, 0xDADADA, 0xBF9F8F, 0xBFAF8F, 0xBFBF8F, 0xAFBF8F,
16
+ 0x9FBF8F, 0x8FBF8F, 0x8FBF9F, 0x8FBFAF, 0x8FBFBF, 0x8FAFBF,
17
+ 0x8F9FBF, 0x8F8FBF, 0x9F8FBF, 0xAF8FBF, 0xBF8FBF, 0xBF8FAF,
18
+ 0xBF8F9F, 0xBF8F8F, 0xB6B6B6, 0xBF7F5F, 0xBFAF8F, 0xBFBF5F,
19
+ 0x9FBF5F, 0x7FBF5F, 0x5FBF5F, 0x5FBF7F, 0x5FBF9F, 0x5FBFBF,
20
+ 0x5F9FBF, 0x5F7FBF, 0x5F5FBF, 0x7F5FBF, 0x9F5FBF, 0xBF5FBF,
21
+ 0xBF5F9F, 0xBF5F7F, 0xBF5F5F, 0x919191, 0xBF6A3F, 0xBF943F,
22
+ 0xBFBF3F, 0x94BF3F, 0x6ABF3F, 0x3FBF3F, 0x3FBF6A, 0x3FBF94,
23
+ 0x3FBFBF, 0x3F94BF, 0x3F6ABF, 0x3F3FBF, 0x6A3FBF, 0x943FBF,
24
+ 0xBF3FBF, 0xBF3F94, 0xBF3F6A, 0xBF3F3F, 0x6D6D6D, 0xFF5500,
25
+ 0xFFAA00, 0xFFFF00, 0xAAFF00, 0x54FF00, 0x00FF00, 0x00FF54,
26
+ 0x00FFAA, 0x00FFFF, 0x00A9FF, 0x0055FF, 0x0000FF, 0x5500FF,
27
+ 0xA900FF, 0xFE00FF, 0xFF00AA, 0xFF0055, 0xFF0000, 0x484848,
28
+ 0xBF3F00, 0xBF7F00, 0xBFBF00, 0x7FBF00, 0x3FBF00, 0x00BF00,
29
+ 0x00BF3F, 0x00BF7F, 0x00BFBF, 0x007FBF, 0x003FBF, 0x0000BF,
30
+ 0x3F00BF, 0x7F00BF, 0xBF00BF, 0xBF007F, 0xBF003F, 0xBF0000,
31
+ 0x242424, 0x7F2A00, 0x7F5500, 0x7F7F00, 0x557F00, 0x2A7F00,
32
+ 0x007F00, 0x007F2A, 0x007F55, 0x007F7F, 0x00547F, 0x002A7F,
33
+ 0x00007F, 0x2A007F, 0x54007F, 0x7F007F, 0x7F0055, 0x7F002A,
34
+ 0x7F0000,
35
+ );
36
+ public static $mountsTFS = [
37
+ 1 => 368, 2 => 369, 3 => 370, 4 => 371, 5 => 372, 6 => 373, 7 => 374, 8 => 375,
38
+ 9 => 376, 10 => 377, 11 => 378, 12 => 379, 13 => 387, 14 => 388, 15 => 389, 16 => 390, 17 => 392,
39
+ 18 => 401, 19 => 402, 20 => 405, 21 => 406, 22 => 421, 23 => 426, 24 => 427, 25 => 437, 26 => 438,
40
+ 27 => 447, 28 => 450, 29 => 502, 30 => 503, 31 => 506, 32 => 515, 33 => 521, 34 => 522, 35 => 526,
41
+ 36 => 546, 37 => 547, 38 => 548, 39 => 559, 40 => 571, 41 => 572, 42 => 580, 43 => 606, 44 => 621,
42
+ 45 => 622, 46 => 624, 47 => 626, 48 => 627, 49 => 628, 50 => 629, 51 => 630, 52 => 631, 53 => 644,
43
+ 54 => 647, 55 => 648, 56 => 649, 57 => 650, 58 => 651, 59 => 669, 60 => 670, 61 => 671, 62 => 672,
44
+ 63 => 673, 64 => 674, 65 => 688, 66 => 689, 67 => 690, 68 => 691, 69 => 692, 70 => 693, 71 => 682,
45
+ 72 => 685, 73 => 686, 74 => 687, 75 => 726, 76 => 727, 77 => 728, 78 => 734, 79 => 735, 80 => 736,
46
+ 81 => 738, 82 => 739, 83 => 740, 84 => 761, 85 => 762, 86 => 763, 87 => 848, 88 => 849, 89 => 850,
47
+ 90 => 851, 91 => 868, 92 => 869, 93 => 870, 94 => 883, 95 => 886, 96 => 887, 97 => 888, 98 => 889,
48
+ 99 => 890, 100 => 901, 101 => 902, 102 => 903, 103 => 905, 104 => 906, 105 => 907, 106 => 937,
49
+ 107 => 950, 108 => 951, 109 => 952, 110 => 959, 111 => 960, 112 => 961, 113 => 1017, 114 => 1018,
50
+ 115 => 1019, 116 => 1025, 117 => 1026, 118 => 1027, 119 => 1049, 120 => 1052, 121 => 1053,
51
+ 122 => 1054, 123 => 1091, 124 => 1092, 125 => 1093, 126 => 1101, 127 => 1104, 128 => 1105,
52
+ 129 => 1106, 130 => 1150, 131 => 1151, 132 => 1163, 133 => 1164, 134 => 1165, 135 => 1167,
53
+ 136 => 1168, 137 => 1169, 138 => 1179, 139 => 1180, 140 => 1181, 141 => 1183, 142 => 1184,
54
+ 143 => 1185, 144 => 1191, 145 => 1208, 146 => 1209, 147 => 1229, 148 => 1230, 149 => 1231,
55
+ 150 => 1232, 151 => 1233, 152 => 1234, 153 => 1247, 154 => 1248, 155 => 1249, 156 => 1257,
56
+ 157 => 1258, 158 => 1259, 159 => 1264, 160 => 1265, 161 => 1266, 162 => 1269, 163 => 1281,
57
+ 164 => 1284, 165 => 1285, 166 => 1286, 167 => 1321, 168 => 1324, 169 => 1325, 170 => 1326,
58
+ 171 => 1333, 172 => 1334, 173 => 1335, 174 => 1336, 175 => 1363, 176 => 1379, 177 => 1380,
59
+ 178 => 1381, 179 => 1389, 180 => 1390, 181 => 1391, 182 => 1417, 183 => 1430, 184 => 1431,
60
+ 185 => 1439, 186 => 1440, 187 => 1441
61
+ ];
62
+
63
+ public static $data = [];
64
+ private static $transparentBackgroundColor = array(255, 255, 255, 127);
65
+ public static $outfitPath;
66
+ public static $resizeAllOutfitsTo64px = false;
67
+
68
+ public static function instance() {
69
+ if (!isset(self::$instance))
70
+ self::$instance = new self();
71
+ return self::$instance;
72
+ }
73
+
74
+ public static function setResizeAllOutfitsTo64px($value) {
75
+ self::$resizeAllOutfitsTo64px = (bool)$value;
76
+ }
77
+
78
+ public static function loadData($outfitId, $isMount = false)
79
+ {
80
+ if($isMount)
81
+ {
82
+ $mount = $outfitId;
83
+ if($mount == 0 || $mount >= 65535)
84
+ {
85
+ $outfitId = ($mount & 0xFFFF);
86
+ }
87
+ elseif($mount < 300)
88
+ {
89
+ // tfs 1.x mount system
90
+ $outfitId = self::$mountsTFS[$mount];
91
+ }
92
+ }
93
+ if(file_exists(self::$outfitPath . $outfitId . '/outfit.data.txt'))
94
+ {
95
+ if($isMount)
96
+ {
97
+ $tmp = unserialize(file_get_contents(self::$outfitPath . $outfitId . '/outfit.data.txt'));
98
+ self::$data['files'] = array_merge(self::$data['files'], $tmp['files']);
99
+ self::$data['mountFramesNumber'] = $tmp['framesNumber'];
100
+ }
101
+ else
102
+ {
103
+ self::$data = unserialize(file_get_contents(self::$outfitPath . $outfitId . '/outfit.data.txt'));
104
+ self::$data['mountFramesNumber'] = 1;
105
+ }
106
+ return true;
107
+ }
108
+ return false;
109
+ }
110
+
111
+ public static function getOutfitFramesNumber()
112
+ {
113
+ return self::$data['framesNumber'];
114
+ }
115
+
116
+ public static function file_exists($filePath)
117
+ {
118
+ return in_array(trim(trim(str_replace('\\', '/', $filePath), '.'), '/'), self::$data['files']);
119
+ }
120
+
121
+ public function outfit($outfit, $addons, $head, $body, $legs, $feet, $mount, $direction = 3, $animation = 1) {
122
+ if($mount == 0 || $mount >= 65535)
123
+ {
124
+ // old mount system
125
+ $mountId = ($mount & 0xFFFF);
126
+ $mountState = (($mount & 0xFFFF0000) != 0) ? 2 : 1;
127
+ }
128
+ elseif($mount < 300)
129
+ {
130
+ // tfs 1.x mount system
131
+ $mountId = self::$mountsTFS[$mount];
132
+ $mountState = 2;
133
+ }
134
+ else
135
+ {
136
+ $mountId = $mount;
137
+ $mountState = 2;
138
+ }
139
+
140
+ if (self::file_exists(self::$outfitPath . $outfit . '/'.$animation.'_' . $mountState . '_1_'.$direction.'.png')) {
141
+ $image_outfit = imagecreatefrompng(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_1_' . $direction . '.png');
142
+ if (file_exists(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_1_' . $direction . '_template.png')) {
143
+ $image_template = imagecreatefrompng(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_1_' . $direction . '_template.png');
144
+ } else {
145
+ $image_template = imagecreatetruecolor(imagesx($image_outfit), imagesy($image_outfit));
146
+ $bgcolor = imagecolorallocatealpha($image_template, self::$transparentBackgroundColor[0], self::$transparentBackgroundColor[1], self::$transparentBackgroundColor[2], self::$transparentBackgroundColor[3]);
147
+ imagefill($image_template, 0, 0, $bgcolor);
148
+ imagecolortransparent($image_template, $bgcolor);
149
+
150
+ imagealphablending($image_template, false);
151
+ imagesavealpha($image_template, true);
152
+ }
153
+
154
+ if ($addons == 1 || $addons == 3) {
155
+ if (self::file_exists(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_2_' . $direction . '.png')) {
156
+ $image_first = imagecreatefrompng(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_2_' . $direction . '.png');
157
+ $this->alphaOverlay($image_outfit, $image_first, 64, 64);
158
+ imagedestroy($image_first);
159
+ if (self::file_exists(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_2_' . $direction . '_template.png')) {
160
+ $image_first_template = imagecreatefrompng(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_2_' . $direction . '_template.png');
161
+ $this->alphaOverlay($image_template, $image_first_template, 64, 64);
162
+ imagedestroy($image_first_template);
163
+ }
164
+ }
165
+ }
166
+ if ($addons == 2 || $addons == 3) {
167
+ if (self::file_exists(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_3_' . $direction . '.png')) {
168
+ $image_second = imagecreatefrompng(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_3_' . $direction . '.png');
169
+ $this->alphaOverlay($image_outfit, $image_second, 64, 64);
170
+ imagedestroy($image_second);
171
+ if (self::file_exists(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_3_' . $direction . '_template.png')) {
172
+ $image_second_template = imagecreatefrompng(self::$outfitPath . $outfit . '/' . $animation . '_' . $mountState . '_3_' . $direction . '_template.png');
173
+ $this->alphaOverlay($image_template, $image_second_template, 64, 64);
174
+ imagedestroy($image_second_template);
175
+ }
176
+ }
177
+ }
178
+
179
+ $this->colorize($image_template, $image_outfit, $head, $body, $legs, $feet);
180
+ }
181
+
182
+ $mountAnimationFrame = $animation;
183
+ while ($mountAnimationFrame > self::$data['mountFramesNumber']) {
184
+ $mountAnimationFrame -= self::$data['mountFramesNumber'];
185
+ }
186
+
187
+ if ($mountState == 2 && self::file_exists(self::$outfitPath . $mountId . '/'.$mountAnimationFrame.'_1_1_'.$direction.'.png')) {
188
+ $mount = imagecreatefrompng(self::$outfitPath . $mountId . '/'.$mountAnimationFrame.'_1_1_'.$direction.'.png');
189
+ $this->alphaOverlay($mount, $image_outfit, 64, 64);
190
+ if ($image_outfit) {
191
+ imagedestroy($image_outfit);
192
+ }
193
+ $image_outfit = $mount;
194
+ }
195
+
196
+ $width = imagesx($image_outfit);
197
+ $height = imagesy($image_outfit);
198
+ if (self::$resizeAllOutfitsTo64px) {
199
+ $image_outfitT = imagecreatetruecolor(64, 64);
200
+ } else {
201
+ $image_outfitT = imagecreatetruecolor($width, $height);
202
+ }
203
+
204
+ // Use a specific color for transparency (Magenta: 255, 0, 255)
205
+ $bgcolor = imagecolorallocate($image_outfitT, 255, 0, 255);
206
+ imagefill($image_outfitT, 0, 0, $bgcolor);
207
+
208
+ imagecopyresampled($image_outfitT, $image_outfit, imagesx($image_outfitT)-$width, imagesy($image_outfitT)-$height, 0, 0, $width, $height, $width, $height);
209
+
210
+ // Convert truecolor image to palette to fix GIF transparency loss issue
211
+ imagetruecolortopalette($image_outfitT, false, 255);
212
+
213
+ // Get the exact transparent index and assign it
214
+ $transparentIndex = imagecolorclosest($image_outfitT, 255, 0, 255);
215
+ imagecolortransparent($image_outfitT, $transparentIndex);
216
+
217
+ imagedestroy($image_outfit);
218
+ if (isset($image_template) && $image_template) {
219
+ imagedestroy($image_template);
220
+ }
221
+ return $image_outfitT;
222
+ }
223
+
224
+ protected function colorizePixel($_color, &$_r, &$_g, &$_b) {
225
+ if ($_color < count(self::$outfitColors))
226
+ $value = self::$outfitColors[$_color];
227
+ else
228
+ $value = 0;
229
+ $ro = ($value & 0xFF0000) >> 16; // rgb outfit
230
+ $go = ($value & 0xFF00) >> 8;
231
+ $bo = ($value & 0xFF);
232
+ $_r = (int) ($_r * ($ro / 255));
233
+ $_g = (int) ($_g * ($go / 255));
234
+ $_b = (int) ($_b * ($bo / 255));
235
+ }
236
+
237
+ protected function colorize(&$_image_template, &$_image_outfit, $_head, $_body, $_legs, $_feet) {
238
+ if (!$_image_template) {
239
+ return;
240
+ }
241
+
242
+ for ($i = 0; $i < imagesy($_image_template); $i++) {
243
+ for ($j = 0; $j < imagesx($_image_template); $j++) {
244
+ $templatepixel = imagecolorat($_image_template, $j, $i);
245
+ $outfit = imagecolorat($_image_outfit, $j, $i);
246
+
247
+ if ($templatepixel == $outfit)
248
+ continue;
249
+
250
+ $rt = ($templatepixel >> 16) & 0xFF;
251
+ $gt = ($templatepixel >> 8) & 0xFF;
252
+ $bt = $templatepixel & 0xFF;
253
+ $ro = ($outfit >> 16) & 0xFF;
254
+ $go = ($outfit >> 8) & 0xFF;
255
+ $bo = $outfit & 0xFF;
256
+
257
+ if ($rt && $gt && !$bt) { // yellow == head
258
+ $this->colorizePixel($_head, $ro, $go, $bo);
259
+ } else if ($rt && !$gt && !$bt) { // red == body
260
+ $this->colorizePixel($_body, $ro, $go, $bo);
261
+ } else if (!$rt && $gt && !$bt) { // green == legs
262
+ $this->colorizePixel($_legs, $ro, $go, $bo);
263
+ } else if (!$rt && !$gt && $bt) { // blue == feet
264
+ $this->colorizePixel($_feet, $ro, $go, $bo);
265
+ } else {
266
+ continue; // if nothing changed, skip the change of pixel
267
+ }
268
+
269
+ imagesetpixel($_image_outfit, $j, $i, imagecolorallocate($_image_outfit, $ro, $go, $bo));
270
+ }
271
+ }
272
+ }
273
+
274
+ protected function alphaOverlay(&$destImg, &$overlayImg, $imgW, $imgH) {
275
+ if (!$overlayImg) {
276
+ return $destImg;
277
+ }
278
+
279
+ for ($y = 0; $y < $imgH; $y++) {
280
+ for ($x = 0; $x < $imgW; $x++) {
281
+ $ovrARGB = imagecolorat($overlayImg, $x, $y);
282
+ $ovrA = ($ovrARGB >> 24) << 1;
283
+ $ovrR = $ovrARGB >> 16 & 0xFF;
284
+ $ovrG = $ovrARGB >> 8 & 0xFF;
285
+ $ovrB = $ovrARGB & 0xFF;
286
+
287
+ $change = false;
288
+ if ($ovrA == 0) {
289
+ $dstR = $ovrR;
290
+ $dstG = $ovrG;
291
+ $dstB = $ovrB;
292
+ $change = true;
293
+ } elseif ($ovrA < 254) {
294
+ $dstARGB = imagecolorat($destImg, $x, $y);
295
+ $dstR = $dstARGB >> 16 & 0xFF;
296
+ $dstG = $dstARGB >> 8 & 0xFF;
297
+ $dstB = $dstARGB & 0xFF;
298
+
299
+ $dstR = (($ovrR * (0xFF - $ovrA)) >> 8) + (($dstR * $ovrA) >> 8);
300
+ $dstG = (($ovrG * (0xFF - $ovrA)) >> 8) + (($dstG * $ovrA) >> 8);
301
+ $dstB = (($ovrB * (0xFF - $ovrA)) >> 8) + (($dstB * $ovrA) >> 8);
302
+ $change = true;
303
+ }
304
+ if ($change) {
305
+ $dstRGB = imagecolorallocatealpha($destImg, $dstR, $dstG, $dstB, 0);
306
+ imagesetpixel($destImg, $x, $y, $dstRGB);
307
+ }
308
+ }
309
+ }
310
+ return $destImg;
311
+ }
312
+ }