diff --git a/.eslintrc.json b/.eslintrc.json
index 0a9c3eb..c4ac0e9 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -21,7 +21,7 @@
"parserOptions": {
"project": [
"./tsconfig.json",
- "./tsconfig.tests.json"
+ "./tsconfig.additional.json"
],
"ecmaVersion": "latest",
"sourceType": "script"
diff --git a/.gitignore b/.gitignore
index 7f36dbf..e29ac65 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,3 @@
-prebuilds
.vscode
.cache
diff --git a/.npmignore b/.npmignore
index fd8052a..7fbc60b 100644
--- a/.npmignore
+++ b/.npmignore
@@ -11,4 +11,5 @@ src
bindings
tests
binding.gyp
-jest.config.ts
\ No newline at end of file
+jest.config.ts
+scripts
\ No newline at end of file
diff --git a/README.md b/README.md
index ff8de97..bf34b53 100644
--- a/README.md
+++ b/README.md
@@ -6,3 +6,286 @@
+# Installing
+
+```
+npm i supercell-swf
+```
+
+# Platforms
+
+Module has been tested on the following platforms:
+
+- Windows (x64)
+- Linux (x64)
+- Android (arm64, through Termux)
+
+All of these platforms have prebuilds for the binary side.
+This means that module on these platforms will work out of the box, without the need to install additional tools.
+
+# Module API
+
+## Vectors and object constructor
+
+To implement interaction of native environment objects from JS environment, a custom implementation of arrays was created. It does not include all functions and some functions work a little differently. But basic functions (and even a little more) for working with arrays of objects are still available.
+- All functions that returned a new array in the built-in array now return this.
+- Push function has also changed its behavior. It accepts an instance of an object of its type. If this object is not an instance, then a new object will be initialized, in constructor of which object will be passed, which will be passed to push function.
+
+## DisplayObject
+This is a generic type for objects that have IDs.
+Objects of this type are:
+- Shape
+- TextField
+- MovieClipModifier
+- MovieClip
+
+## Module
+After importing the module, you will have access to an object that contains:
+
+## CompressionSignature
+
+An enum that contains all compressed types that are supported
+
+Types of compressions that are supported:
+- LZMA
+- LZHAM
+- ZSTD
+
+## SupercellCompression
+This object is needed to compress or get content from compressed Supercell files such as .sc or compressed .csv files.
+Has 2 sub-objects for compression and decompression.
+
+Decompressor:
+- decompressFile:
+Decompresses the file at the specified path to cache folder, and returns path to decompressed file.
+
+- decompress:
+Accepts a buffer and returns decompressed content
+
+- commonDecompress:
+Accepts a file buffer, something like a compressed .csv
+
+All functions in Compressor have as argument CompressionSignature which specifies what kind of compression file or buffer will have
+Compressor:
+- compressFile:
+Compresses a file from specified file to another specified file with specified compression type.
+Can accept a buffer for metadata to be inserted at the end of file.
+- compress:
+Compresses a buffer with specified compression type and returns a compressed "SC" buffer.
+It can also accept a buffer with metadata.
+- commonCompress:
+Compresses the buffer with the specified compression type and returns the compressed buffer without additional headers. Needed for .csv files.
+
+## SupercellSWF
+This is the main class for loading .sc files.
+It has variables:
+- useExternalTexture:
+Boolean which shows whether external "_tex.sc" texture will be saved
+- useMultiResTexture:
+When this and useExternalTexture variable is enabled, creates a texture file with multiResSuffix and a lowres file with lowResSuffix, regardless of whether hasLowresTexture is enabled.
+- useLowResTexture:
+Specifies whether file can automatically use lowres file.
+- multiResSuffix:
+Suffix for MultiRes texture.
+- lowResSuffix:
+Suffix for LowRes texture.
+
+It contains vectors (arrays) of objects for:
+- Export names
+- MovieClips
+- TextFields
+- Shapes
+- MatrixBanks
+- MovieClipModifiers
+- SWFTexture
+
+About all these objects below
+
+## ExportName
+Export name is needed to point to some DisplayObject and specify its name for use outside the file area
+It has variables:
+- id:
+DisplayObject ID
+- name
+name for DisplayObject
+
+## PixelFormat
+Enum for SWFTexture which describes pixel types from data buffer
+Has following types:
+- RGBA8
+- RGBA4
+- RGB5_A1
+- RGB565
+- LUMINANCE8_ALPHA8
+- LUMINANCE8
+A description of each type and how to read them can be easily found on internet.
+
+## Filters
+Enum for SWFTexture which describes filters for textures
+Has following types:
+- LINEAR
+- NEAREST
+- LINEAR_MIPMAP_NEAREST
+
+## SWFTexture
+Texture atlas that contains all sprites
+It has variables:
+- width
+- height
+- pixelFormat:
+Uses PixelFormat enum to describe a pixel type
+- downscaling
+- magFilter:
+Uses Filter enum to describe filter type
+- minFilter
+- data:
+Buffer with image raw data
+
+## ModifierType
+Enum for MovieClipModifier which describes modifier type
+Has following types:
+- Mask:
+Means that the next element will be rendered as a mask-layer
+- Masked:
+Means that all elements after this modifier will be rendered as masked layers of the previous mask layer.
+- Unmasked:
+Marks the end of Masked modifier
+
+## MovieClipModifier
+Included as a render object for use in frames to "modify" them
+It has variables:
+- type:
+Uses ModifierType enum to describe type of modification.
+
+## ShapeDrawCommandVertex
+Class for storing information about vertices in ShapeDrawBitmapCommand
+It has variables:
+- x
+- y
+- u
+- v
+
+## ShapeDrawBitmapCommand
+Class for rendering a sprite from a texture
+It has variables:
+- textureIndex:
+Index of texture from textures vector in SupercellSWF class
+It contains vector:
+- vertices:
+Contains ShapeDrawCommandVertex objects
+
+## Shape
+Command storage
+It contains vector:
+- commands:
+Contains ShapeDrawBitmapCommand objects
+
+## TextField
+Objects that store text properties
+It has variables:
+- text
+- fontName
+- fontColor
+- fontSize
+- fontAlign:
+Maybe using bits to compactly fit some other boolean values
+- left
+- top
+- right
+- bottom
+- isBold
+- isItalic
+- isMultiline
+- isOutlined
+- outlineColor
+- useDeviceFont
+- autoAdjustFontBounds
+It also has some unknown flags, they are just there to make sure some files are saved correctly
+- unknownFlag
+- unknownShort
+- unknownShort2
+
+## MatrixBank
+Object for placing matrices and color transformations. Needed to expand limit (UINT16_MAX) of transformations in file.
+It contains vectors:
+- matrices:
+Array of Matrix2x3
+- colorTransformations:
+Vector of ColorTransofmation
+
+## Matrix2x3
+Affine 2z3 matrix for transforming objects on screen
+
+## ColorTransform
+Manipulates color properties of an object on screen
+
+## DisplayObjectInstance
+Also known as "Movie Clip Bind". Needed to specify a "link" to another DisplayObject in a MovieClip
+It has variables:
+- id
+- blend:
+index of blend mode
+- name:
+name of "link"
+
+## MovieClipFrame
+An object that describes number of MovieClipFrameElement that frame should use
+It has variable:
+- elementsCount
+- label
+
+## MovieClipFrameElement
+Object with object transformation and index to DisplayObjectInstance
+It has variables:
+- instanceIndex:
+index to DisplayObjectInstance
+- matrixIndex
+index to Matrix2x3 in MatrixBank
+- colorTransformIndex
+index to ColorTransformation in MatrixBank
+
+## MovieClip
+Storage for DisplayObjectInstance, MovieClipFrame, MovieClipFrameElement
+It has variables:
+- frameRate:
+frame per second
+- scalingGrid:
+also known as 9-slice or nine-slice
+- matrixBankIndex:
+Bank index in matrixBanks in SupercellSWF. Used to get transformations from MovieClipFrameElement
+It contains vectors:
+- instances:
+Array of DisplayObjectInstance (or binds)
+- frames:
+Array of MovieClipFrame
+- frameElements:
+Array of MovieClipFrameElement
+
+# Building
+Please note that the module may not build correctly on platforms where it has not been tested.
+
+Before you begin, you will need to install the C++ build tools.
+On Windows, you can do this by installing Visual studio.
+On Linux, you can install the "build-essential" package.
+
+First you need to clone this repository with command:
+```
+git clone https://github.com/scwmake/SupercellSWF-JS.git
+```
+Then go to repo folder
+```
+cd SupercellSWF-JS
+```
+Update submodules
+```
+git subomodules update --remote
+```
+Run command
+```
+npm i --save-dev
+```
+
+If node-gyp and typescript are configured correctly, then after that JS side will be compiled and then native side.
+
+# Any questions?
+For any questions or help, you can contact me using Discord: "Daniil SV#6571"
\ No newline at end of file
diff --git a/bindings/SupercellCompressionNapi/Compressor.cpp b/bindings/SupercellCompressionNapi/Compressor.cpp
index f166f10..fff800d 100644
--- a/bindings/SupercellCompressionNapi/Compressor.cpp
+++ b/bindings/SupercellCompressionNapi/Compressor.cpp
@@ -12,7 +12,7 @@ namespace scNapi
if (!info[3].IsUndefined())
{
- Napi::Buffer metadataNapi = info[0].As>();
+ Napi::Buffer metadataNapi = info[3].As>();
metadata = new std::vector(metadataNapi.Length());
memcpy(metadata->data(), metadataNapi.Data(), metadata->size());
}
@@ -45,12 +45,16 @@ namespace scNapi
if (!info[2].IsUndefined())
{
- Napi::Buffer metadataNapi = info[1].As>();
+ Napi::Buffer metadataNapi = info[2].As>();
metadata = new std::vector(metadataNapi.Length());
memcpy(metadata->data(), metadataNapi.Data(), metadata->size());
}
- sc::Compressor::compress(inputStream, outputStream, (sc::CompressionSignature)info[1].ToNumber().Uint32Value(), metadata);
+ sc::Compressor::compress(
+ inputStream,
+ outputStream,
+ (sc::CompressionSignature)ToNativeValue(info[1]),
+ metadata);
/* Vector to buffer */
Napi::Buffer buffer = Napi::Buffer::Copy(env, outputBuffer.data(), outputBuffer.size());
diff --git a/jest.config.ts b/jest.config.ts
index 0751b46..ed7e257 100644
--- a/jest.config.ts
+++ b/jest.config.ts
@@ -1,11 +1,6 @@
export default {
- // All imported modules in your tests should be mocked automatically
- // automock: false,
-
- // Stop running tests after `n` failures
- // bail: 1,
-
+ bail: true,
// The directory where Jest should store its cached dependency information
cacheDirectory: ".cache",
diff --git a/package.json b/package.json
index d6d14ac..45b64d2 100644
--- a/package.json
+++ b/package.json
@@ -6,11 +6,12 @@
"types": "./types/index.d.ts",
"scripts": {
"install": "node-gyp-build",
- "prepack": "npm test & npm run build:ts",
+ "prepublishOnly": "npm run test",
+ "prepack": "npm run build & npm test",
+ "build": "npm rum build:native & npm run build:ts",
"build:ts": "tsc",
"build:native": "node-gyp build",
- "build:native-debug": "node-gyp build --debug",
- "prebuild": "prebuildify --napi",
+ "prebuild": "prebuildify --napi && node scripts/after_build.js",
"test": "jest"
},
"devDependencies": {
@@ -40,7 +41,7 @@
"license": "MIT",
"repository": {
"type": "git",
- "url": "https://github.com/scwmake/supercell-swf-ts.git"
+ "url": "https://github.com/scwmake/SupercellSWF-JS.git"
},
"dependencies": {
"node-gyp-build": "^4.5.0"
diff --git a/prebuilds/linux-x64/node.napi.node b/prebuilds/linux-x64/node.napi.node
new file mode 100644
index 0000000..2c46b58
Binary files /dev/null and b/prebuilds/linux-x64/node.napi.node differ
diff --git a/prebuilds/linux-x64/version b/prebuilds/linux-x64/version
new file mode 100644
index 0000000..359a5b9
--- /dev/null
+++ b/prebuilds/linux-x64/version
@@ -0,0 +1 @@
+2.0.0
\ No newline at end of file
diff --git a/prebuilds/win32-x64/node.napi.node b/prebuilds/win32-x64/node.napi.node
new file mode 100644
index 0000000..1a0d5ba
Binary files /dev/null and b/prebuilds/win32-x64/node.napi.node differ
diff --git a/prebuilds/win32-x64/version b/prebuilds/win32-x64/version
new file mode 100644
index 0000000..359a5b9
--- /dev/null
+++ b/prebuilds/win32-x64/version
@@ -0,0 +1 @@
+2.0.0
\ No newline at end of file
diff --git a/scripts/after_build.js b/scripts/after_build.js
new file mode 100644
index 0000000..c4f341f
--- /dev/null
+++ b/scripts/after_build.js
@@ -0,0 +1,27 @@
+const os = require("os");
+const fs = require("fs");
+const path = require("path");
+
+const manifest = require("../package.json");
+
+const platform = os.platform();
+const arch = os.arch();
+
+const version = manifest.version;
+
+const codename = `${platform}-${arch}`;
+const prebuildPath = path.join(path.resolve(__dirname, "../"), "prebuilds");
+
+const destPath = path.join(prebuildPath, codename);
+
+const destModulePath = path.join(destPath, "node.napi.node");
+
+if (!fs.existsSync(destPath)) {
+ throw new Error("Native module folder not found!");
+}
+
+if (!fs.existsSync(destModulePath)) {
+ throw new Error("Native module not found or compiled incorrectly!");
+}
+
+fs.writeFileSync(path.join(destPath, "version"), version);
diff --git a/src/native/native.ts b/src/native/native.ts
index 648daaf..fc980ae 100644
--- a/src/native/native.ts
+++ b/src/native/native.ts
@@ -45,7 +45,14 @@ declare interface NativeInterface {
DisplayObjectInstance: typeof DisplayObjectInstance;
}
-// eslint-disable-next-line @typescript-eslint/no-var-requires
-export const native: NativeInterface = require("node-gyp-build")(
- path.resolve(__dirname, "../../")
-);
+export let native: NativeInterface;
+
+try {
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
+ native = require("node-gyp-build")(path.resolve(__dirname, "../../"));
+} catch (err) {
+ console.error(err);
+ throw new Error(
+ "Failed to load SupercellSWF native side. Most likely there is no binary prebuild for your platform. Try to make a build yourself. Details can be found at https://github.com/scwmake/SupercellSWF-JS"
+ );
+}
diff --git a/tests/module.test.ts b/tests/module.test.ts
new file mode 100644
index 0000000..c09ff65
--- /dev/null
+++ b/tests/module.test.ts
@@ -0,0 +1,18 @@
+import { expect, test } from "@jest/globals";
+import { readdirSync, readFileSync } from "fs";
+import { join, resolve } from "path";
+
+import { version } from "../package.json";
+
+const prebuildFolder = join(resolve(__dirname, "../"), "prebuilds");
+
+describe("Native module tests", () => {
+ test("Versions of all native modules must be as in package", () => {
+ const prebuildContent = readdirSync(prebuildFolder);
+ for (const prebuildPlatformName of prebuildContent) {
+ const prebuildPlatformPath = join(prebuildFolder, prebuildPlatformName);
+ const moduleVersion = readFileSync(join(prebuildPlatformPath, "version"));
+ expect(String(moduleVersion)).toBe(version);
+ }
+ });
+});
diff --git a/tsconfig.tests.json b/tsconfig.additional.json
similarity index 67%
rename from tsconfig.tests.json
rename to tsconfig.additional.json
index df0bd20..48c5a2c 100644
--- a/tsconfig.tests.json
+++ b/tsconfig.additional.json
@@ -1,7 +1,8 @@
{
"extends": "./tsconfig.json",
"include": [
- "tests/**/*.ts"
+ "tests/**/*.ts",
+ "scripts/**/*.js"
],
"exclude": [
"node_modules/"