miijs 2.1.1 → 2.1.2

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.
package/fflWrapper.js ADDED
@@ -0,0 +1,41 @@
1
+ // Compatibility layer for ffl.js
2
+ const structFu = require('struct-fu');
3
+
4
+ // Monkey-patch struct-fu BEFORE ffl.js loads
5
+ const originalStruct = structFu.struct;
6
+ structFu.struct = function(...args) {
7
+ const result = originalStruct.apply(this, args);
8
+ const originalUnpack = result.unpack;
9
+ const originalPack = result.pack;
10
+
11
+ result.unpack = function(data) {
12
+ if (data && !(data instanceof Buffer) && data.buffer) {
13
+ data = Buffer.from(data);
14
+ }
15
+ return originalUnpack.call(this, data);
16
+ };
17
+
18
+ result.pack = function(obj) {
19
+ if (obj && typeof obj === 'object') {
20
+ for (let key in obj) {
21
+ if (key.startsWith('_padding') && Array.isArray(obj[key])) {
22
+ obj[key] = Buffer.from(obj[key]);
23
+ }
24
+ }
25
+ }
26
+ return originalPack.call(this, obj);
27
+ };
28
+
29
+ return result;
30
+ };
31
+
32
+ // Set up globals
33
+ global._ = structFu;
34
+ global.THREE = require('three');
35
+
36
+ // Load ffl.js - it will use the patched struct-fu
37
+ const fflPath = require.resolve('ffl.js/ffl.js');
38
+ delete require.cache[fflPath]; // Clear cache
39
+ const fflModule = require('ffl.js/ffl.js');
40
+
41
+ module.exports = fflModule;
package/index.js CHANGED
@@ -12,12 +12,11 @@ const asmCrypto=require("./asmCrypto.js");
12
12
  const path=require("path");
13
13
  const createGL = require('gl');
14
14
 
15
- const req=require("require-esm-in-cjs");
16
15
  const {
17
16
  createCharModel, initCharModelTextures,
18
17
  initializeFFL, exitFFL, parseHexOrB64ToUint8Array,
19
18
  setIsWebGL1State, getCameraForViewType, ViewType
20
- } = req("ffl.js/ffl.js");
19
+ } = require("./fflWrapper.js");
21
20
  const ModuleFFL = require("ffl.js/examples/ffl-emscripten-single-file.js");
22
21
  const FFLShaderMaterial = require("ffl.js/FFLShaderMaterial.js");
23
22
 
@@ -65,8 +64,11 @@ function getFFLRes() {
65
64
  // If we've already tried loading, just return the result
66
65
  if (_fflRes !== undefined) return _fflRes;
67
66
  for (const path of [ "./FFLResHigh.dat", "./ffl/FFLResHigh.dat" ]) {
68
- if (fs.existsSync(path))
69
- return _fflRes = new Uint8Array(fs.readFileSync(path));
67
+ if (fs.existsSync(path)) {
68
+ // Convert Buffer to Uint8Array explicitly
69
+ const buffer = fs.readFileSync(path);
70
+ return _fflRes = new Uint8Array(buffer);
71
+ }
70
72
  }
71
73
  // If no file found, mark as null
72
74
  return _fflRes = null;
@@ -1955,9 +1957,9 @@ function convertMiiToStudio(jsonIn) {
1955
1957
  var mii = jsonIn;
1956
1958
  var studioMii = new Uint8Array([0x08, 0x00, 0x40, 0x03, 0x08, 0x04, 0x04, 0x02, 0x02, 0x0c, 0x03, 0x01, 0x06, 0x04, 0x06, 0x02, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x0a, 0x01, 0x00, 0x21, 0x40, 0x04, 0x00, 0x02, 0x14, 0x03, 0x13, 0x04, 0x17, 0x0d, 0x04, 0x00, 0x0a, 0x04, 0x01, 0x09]);
1957
1959
  studioMii[0x16] = mii.general.gender;
1958
- studioMii[0x15] = mii.info.favoriteColor;
1959
- studioMii[0x1E] = mii.info.height;
1960
- studioMii[2] = mii.info.weight;
1960
+ studioMii[0x15] = mii.general.favoriteColor;
1961
+ studioMii[0x1E] = mii.general.height;
1962
+ studioMii[2] = mii.general.weight;
1961
1963
  studioMii[0x13] = lookupTables.faces.values[mii.face.type];
1962
1964
  studioMii[0x11] = mii.face.color;
1963
1965
  studioMii[0x14] = mii.face.feature;
@@ -1985,7 +1987,7 @@ function convertMiiToStudio(jsonIn) {
1985
1987
  studioMii[0x2B] = mii.nose.size;
1986
1988
  studioMii[0x2D] = mii.nose.yPosition;
1987
1989
  studioMii[0x26] = lookupTables.mouths.values[mii.mouth.page][mii.mouth.type];
1988
- studioMii[0x24] = mii.mouth.col;
1990
+ studioMii[0x24] = mii.mouth.color;
1989
1991
  if (studioMii[0x24] < 4) {
1990
1992
  studioMii[0x24] += 19;
1991
1993
  } else {
@@ -1993,15 +1995,15 @@ function convertMiiToStudio(jsonIn) {
1993
1995
  }
1994
1996
  studioMii[0x25] = mii.mouth.size;
1995
1997
  studioMii[0x23] = mii.mouth.squash;
1996
- studioMii[0x27] = mii.mouth.yPos;
1997
- studioMii[0x29] = mii.facialHair.mustacheType;
1998
- studioMii[1] = mii.facialHair.beardType;
1999
- studioMii[0] = lookupTables.hairCols.indexOf(mii.facialHair.col);
1998
+ studioMii[0x27] = mii.mouth.yPosition;
1999
+ studioMii[0x29] = mii.beard.mustache.type;
2000
+ studioMii[1] = mii.beard.beardType;
2001
+ studioMii[0] = mii.beard.color;
2000
2002
  if (!studioMii[0]) studioMii[0] = 8;
2001
- studioMii[0x28] = mii.facialHair.mustacheSize;
2002
- studioMii[0x2A] = mii.facialHair.mustacheYPos;
2003
+ studioMii[0x28] = mii.beard.mustache.size;
2004
+ studioMii[0x2A] = mii.beard.mustache.yPosition;
2003
2005
  studioMii[0x19] = mii.glasses.type;
2004
- studioMii[0x17] = lookupTables.glassesCols3DS.indexOf(mii.glasses.col);
2006
+ studioMii[0x17] = mii.glasses.color;
2005
2007
  if (!studioMii[0x17]) {
2006
2008
  studioMii[0x17] = 8;
2007
2009
  } else if (studioMii[0x17] < 6) {
@@ -2115,16 +2117,20 @@ async function createFFLMiiIcon(data, width, height, fflRes) {
2115
2117
 
2116
2118
  let ffl, currentCharModel;
2117
2119
 
2118
- //const _realConsoleDebug = console.debug;
2119
- //console.debug = () => { };
2120
+ const _realConsoleDebug = console.debug;
2121
+ console.debug = () => { };
2120
2122
  try {
2121
2123
  // Initialize FFL
2122
2124
  ffl = await initializeFFL(fflRes, ModuleFFL);
2123
2125
 
2124
2126
  // Create Mii model and add to the scene.
2125
2127
  const studioRaw = parseHexOrB64ToUint8Array(data); // Parse studio data
2126
- currentCharModel = createCharModel(studioRaw, null,
2127
- FFLShaderMaterial, ffl.module);
2128
+
2129
+ // Convert Uint8Array to Buffer for struct-fu compatibility
2130
+ const studioBuffer = Buffer.from(studioRaw);
2131
+
2132
+ currentCharModel = createCharModel(studioBuffer, null,
2133
+ FFLShaderMaterial, ffl.module);
2128
2134
  initCharModelTextures(currentCharModel, renderer); // Initialize fully
2129
2135
  scene.add(currentCharModel.meshes); // Add to scene
2130
2136
 
@@ -2170,13 +2176,13 @@ async function createFFLMiiIcon(data, width, height, fflRes) {
2170
2176
  }
2171
2177
  }
2172
2178
  async function renderMii(jsonIn, fflRes=getFFLRes()){
2173
- if(!["3ds","wii u"].includes(jsonIn.console?.toLowerCase())){
2174
- jsonIn=convertMii(jsonIn);
2175
- }
2176
- const studioMii = convertMiiToStudio(jsonIn);
2177
- const width = height = 600;
2179
+ if(!["3ds","wii u"].includes(jsonIn.console?.toLowerCase())){
2180
+ jsonIn=convertMii(jsonIn);
2181
+ }
2182
+ const studioMii = convertMiiToStudio(jsonIn);
2183
+ const width = height = 600;
2178
2184
 
2179
- return createFFLMiiIcon(studioMii, width, height, fflRes);
2185
+ return createFFLMiiIcon(studioMii, width, height, fflRes);
2180
2186
  }
2181
2187
  async function writeWiiBin(jsonIn, outPath) {
2182
2188
  if (jsonIn.console?.toLowerCase() !== "wii") {
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "miijs",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "description": "Work with Mii characters in every possible way needed for your project.",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "jest"
7
+ "test": "jest",
8
+ "postinstall": "node ./patch-ffl.js"
8
9
  },
9
10
  "repository": {
10
11
  "type": "git",
@@ -26,7 +27,7 @@
26
27
  "homepage": "https://github.com/KestronProgramming/MiiJS#readme",
27
28
  "dependencies": {
28
29
  "canvas": "^3.1.0",
29
- "ffl.js": "github:ariankordi/FFL.js#4f83ae2",
30
+ "ffl.js": "github:ariankordi/FFL.js#06ede8f",
30
31
  "gl": "^8.1.6",
31
32
  "https": "^1.0.0",
32
33
  "jimp": "0.22.12",
@@ -35,6 +36,7 @@
35
36
  "path": "^0.12.7",
36
37
  "qr-code-styling": "^1.9.2",
37
38
  "require-esm-in-cjs": "^0.1.0",
39
+ "struct-fu": "^1.2.1",
38
40
  "three": "^0.162.0"
39
41
  },
40
42
  "devDependencies": {
package/patch-ffl.js ADDED
@@ -0,0 +1,48 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const fflPath = path.join(__dirname, './node_modules/ffl.js/ffl.js');
5
+
6
+ console.log('Patching ffl.js to have CJS Exports...');
7
+
8
+ if (!fs.existsSync(fflPath)) {
9
+ console.error('ffl.js not found at', fflPath);
10
+ process.exit(1);
11
+ }
12
+
13
+ let content = fs.readFileSync(fflPath, 'utf8');
14
+
15
+ // Check if already patched
16
+ if (content.includes('// MIIJS_PATCHED')) {
17
+ console.log('ffl.js already patched, skipping.');
18
+ process.exit(0);
19
+ }
20
+
21
+ content += `
22
+ // MIIJS_PATCHED - CommonJS exports for Node.js
23
+ if (typeof module !== 'undefined' && module.exports) {
24
+ module.exports = {
25
+ initializeFFL,
26
+ exitFFL,
27
+ createCharModel,
28
+ initCharModelTextures,
29
+ setIsWebGL1State,
30
+ parseHexOrB64ToUint8Array,
31
+ getCameraForViewType,
32
+ ViewType,
33
+ CharModel,
34
+ FFLExpression,
35
+ FFLModelFlag,
36
+ FFLResourceType,
37
+ makeExpressionFlag,
38
+ TextureShaderMaterial,
39
+ convertStudioCharInfoToFFLiCharInfo,
40
+ convertFFLiCharInfoToStudioCharInfo,
41
+ uint8ArrayToBase64
42
+ };
43
+ }
44
+ `;
45
+ content=content.replaceAll("console.debug","//console.debug");
46
+ fs.writeFileSync(fflPath, content, 'utf8');
47
+
48
+ console.log('ffl.js successfully patched.');
package/out.txt DELETED
@@ -1,178 +0,0 @@
1
- {
2
- "mouth": {
3
- "0": 6,
4
- "1": 1,
5
- "2": 2,
6
- "3": 4,
7
- "4": 5,
8
- "5": 5,
9
- "6": 10,
10
- "7": 0,
11
- "8": 7,
12
- "9": 1,
13
- "10": 8,
14
- "11": 7,
15
- "12": 11,
16
- "13": 11,
17
- "14": 10,
18
- "15": 6,
19
- "16": 9,
20
- "17": 3,
21
- "18": 9,
22
- "19": 2,
23
- "20": 8,
24
- "21": 3,
25
- "22": 4,
26
- "23": 0
27
- },
28
- "eyebrows": {
29
- "0": 1,
30
- "1": 3,
31
- "2": 2,
32
- "3": 3,
33
- "4": 11,
34
- "5": 10,
35
- "6": 0,
36
- "7": 6,
37
- "8": 8,
38
- "9": 4,
39
- "10": 1,
40
- "11": 0,
41
- "12": 2,
42
- "13": 7,
43
- "14": 4,
44
- "15": 6,
45
- "16": 10,
46
- "17": 9,
47
- "18": 9,
48
- "19": 5,
49
- "20": 5,
50
- "21": 7,
51
- "22": 8,
52
- "23": 11
53
- },
54
- "eyes": {
55
- "0": 2,
56
- "1": 6,
57
- "2": 0,
58
- "3": 6,
59
- "4": 1,
60
- "5": 0,
61
- "6": 5,
62
- "7": 0,
63
- "8": 3,
64
- "9": 4,
65
- "10": 9,
66
- "11": 1,
67
- "12": 5,
68
- "13": 2,
69
- "14": 10,
70
- "15": 9,
71
- "16": 8,
72
- "17": 5,
73
- "18": 9,
74
- "19": 2,
75
- "20": 11,
76
- "21": 8,
77
- "22": 8,
78
- "23": 6,
79
- "24": 6,
80
- "25": 9,
81
- "26": 7,
82
- "27": 10,
83
- "28": 10,
84
- "29": 5,
85
- "30": 7,
86
- "31": 8,
87
- "32": 3,
88
- "33": 0,
89
- "34": 7,
90
- "35": 11,
91
- "36": 3,
92
- "37": 4,
93
- "38": 2,
94
- "39": 4,
95
- "40": 10,
96
- "41": 1,
97
- "42": 3,
98
- "43": 7,
99
- "44": 1,
100
- "45": 4,
101
- "46": 11,
102
- "47": 11
103
- },
104
- "hairs": {
105
- "0": 11,
106
- "1": 6,
107
- "2": 5,
108
- "3": 1,
109
- "4": 4,
110
- "5": 8,
111
- "6": 4,
112
- "7": 11,
113
- "8": 9,
114
- "9": 3,
115
- "10": 3,
116
- "11": 6,
117
- "12": 0,
118
- "13": 1,
119
- "14": 0,
120
- "15": 10,
121
- "16": 1,
122
- "17": 8,
123
- "18": 4,
124
- "19": 7,
125
- "20": 5,
126
- "21": 10,
127
- "22": 2,
128
- "23": 3,
129
- "24": 9,
130
- "25": 5,
131
- "26": 3,
132
- "27": 10,
133
- "28": 6,
134
- "29": 11,
135
- "30": 9,
136
- "31": 11,
137
- "32": 0,
138
- "33": 0,
139
- "34": 11,
140
- "35": 9,
141
- "36": 6,
142
- "37": 2,
143
- "38": 1,
144
- "39": 4,
145
- "40": 1,
146
- "41": 7,
147
- "42": 2,
148
- "43": 0,
149
- "44": 3,
150
- "45": 6,
151
- "46": 2,
152
- "47": 1,
153
- "48": 3,
154
- "49": 7,
155
- "50": 7,
156
- "51": 2,
157
- "52": 5,
158
- "53": 7,
159
- "54": 5,
160
- "55": 8,
161
- "56": 9,
162
- "57": 10,
163
- "58": 6,
164
- "59": 8,
165
- "60": 10,
166
- "61": 0,
167
- "62": 11,
168
- "63": 7,
169
- "64": 9,
170
- "65": 8,
171
- "66": 4,
172
- "67": 4,
173
- "68": 10,
174
- "69": 2,
175
- "70": 5,
176
- "71": 8
177
- }
178
- }
package/stuff.js DELETED
@@ -1,208 +0,0 @@
1
- var types={
2
- mouth: {
3
- '0': '113',
4
- '1': '121',
5
- '2': '131',
6
- '3': '122',
7
- '4': '132',
8
- '5': '132',
9
- '6': '124',
10
- '7': '111',
11
- '8': '123',
12
- '9': '121',
13
- '10': '133',
14
- '11': '123',
15
- '12': '134',
16
- '13': '134',
17
- '14': '124',
18
- '15': '113',
19
- '16': '114',
20
- '17': '112',
21
- '18': '114',
22
- '19': '131',
23
- '20': '133',
24
- '21': '112',
25
- '22': '122',
26
- '23': '111'
27
- },
28
- eyebrows:{
29
- '0': '121',
30
- '1': '112',
31
- '2': '231',
32
- '3': '212',
33
- '4': '134',
34
- '5': '124',
35
- '6': '111',
36
- '7': '113',
37
- '8': '133',
38
- '9': '122',
39
- '10': '221',
40
- '11': '211',
41
- '12': '131',
42
- '13': '223',
43
- '14': '222',
44
- '15': '213',
45
- '16': '224',
46
- '17': '114',
47
- '18': '214',
48
- '19': '132',
49
- '20': '232',
50
- '21': '123',
51
- '22': '233',
52
- '23': '234'
53
- },
54
- eyes:{
55
- '0': '131',
56
- '1': '113',
57
- '2': '111',
58
- '3': '413',
59
- '4': '121',
60
- '5': '311',
61
- '6': '332',
62
- '7': '411',
63
- '8': '112',
64
- '9': '222',
65
- '10': '414',
66
- '11': '221',
67
- '12': '232',
68
- '13': '331',
69
- '14': '424',
70
- '15': '114',
71
- '16': '133',
72
- '17': '132',
73
- '18': '314',
74
- '19': '231',
75
- '20': '134',
76
- '21': '233',
77
- '22': '433',
78
- '23': '213',
79
- '24': '313',
80
- '25': '214',
81
- '26': '123',
82
- '27': '124',
83
- '28': '324',
84
- '29': '432',
85
- '30': '323',
86
- '31': '333',
87
- '32': '212',
88
- '33': '211',
89
- '34': '223',
90
- '35': '234',
91
- '36': '312',
92
- '37': '322',
93
- '38': '431',
94
- '39': '122',
95
- '40': '224',
96
- '41': '321',
97
- '42': '412',
98
- '43': '423',
99
- '44': '421',
100
- '45': '422',
101
- '46': '334',
102
- '47': '434'
103
- },
104
- hairs:{
105
- '0': '534',
106
- '1': '413',
107
- '2': '632',
108
- '3': '521',
109
- '4': '422',
110
- '5': '433',
111
- '6': '522',
112
- '7': '434',
113
- '8': '414',
114
- '9': '612',
115
- '10': '512',
116
- '11': '513',
117
- '12': '411',
118
- '13': '421',
119
- '14': '511',
120
- '15': '624',
121
- '16': '621',
122
- '17': '533',
123
- '18': '622',
124
- '19': '423',
125
- '20': '532',
126
- '21': '524',
127
- '22': '531',
128
- '23': '312',
129
- '24': '614',
130
- '25': '432',
131
- '26': '412',
132
- '27': '424',
133
- '28': '613',
134
- '29': '634',
135
- '30': '314',
136
- '31': '134',
137
- '32': '211',
138
- '33': '111',
139
- '34': '334',
140
- '35': '514',
141
- '36': '313',
142
- '37': '231',
143
- '38': '321',
144
- '39': '122',
145
- '40': '121',
146
- '41': '323',
147
- '42': '331',
148
- '43': '311',
149
- '44': '112',
150
- '45': '113',
151
- '46': '631',
152
- '47': '221',
153
- '48': '212',
154
- '49': '123',
155
- '50': '223',
156
- '51': '131',
157
- '52': '232',
158
- '53': '623',
159
- '54': '332',
160
- '55': '233',
161
- '56': '114',
162
- '57': '324',
163
- '58': '213',
164
- '59': '133',
165
- '60': '224',
166
- '61': '611',
167
- '62': '234',
168
- '63': '523',
169
- '64': '214',
170
- '65': '333',
171
- '66': '222',
172
- '67': '322',
173
- '68': '124',
174
- '69': '431',
175
- '70': '132',
176
- '71': '633'
177
- }
178
- };
179
- var types2={};
180
- var mappings=[
181
- 11,21,31,
182
- 12,22,32,
183
- 13,23,33,
184
- 14,24,34];
185
- Object.keys(types).forEach(key=>{
186
- types2[key]={};
187
- Object.keys(types[key]).forEach(num=>{
188
- types2[key][num]=mappings.indexOf(+(types[key][num].slice(1,3)));
189
-
190
- });
191
- });
192
- require("fs").writeFileSync("./out.txt",JSON.stringify(types2,0,4));
193
-
194
-
195
- /*
196
- How it should be
197
- 0, 1, 2
198
- 3, 4, 5
199
- 6, 7, 8
200
- 9,10,11
201
-
202
- How it is
203
- 11,21,31,
204
- 12,22,32,
205
- 13,23,33,
206
- 14,24,34
207
- */
208
-