You're absolutely right!
Since JS doesn't actually enforce access control, people seem to be more prone to ignore privacy, but that's bad and comes back to bite you in the ass later if you're not careful.
Back to your question:
The answer here is not to make the Window access the array, but to add the commands from the array into the window.
What Window_Command does is basically maintain a list of
(name, symbol) pairs, where
name is what you see on the screen and
symbol is used internally to handle the actual command (this is the important part). Usually it's constructed statically on
makeCommandList, which fundamentally works as some kind of "abstract constructor", but you could just as easily use it to build the command list from a list of your own. Like this:
Code:
function Window_MyCommands() {
this.initialize(...arguments);
}
Window_MyCommands.prototype = Object.create(Window_Command.prototype);
Window_MyCommands.prototype.constructor = Window_MyCommands;
Window_MyCommands.prototype.initialize = function(rect) {
Window_Command.prototype.initialize.call(this, rect);
this._commands = [];
};
Window_MyCommands.prototype.addCustomCommand = function(name, symbol) {
this._commands.push({ name, symbol });
};
Window_MyCommands.prototype.makeCommandList = function() {
this._commands.forEach(({ name, symbol }) => this.addCommand(name, symbol));
};
Then you can add new commands to your window like this:
Code:
let myWindow = new Window_MyCommands(someRect);
// ... Then, somewhere else when you've decided the commands you need:
myWindow.addCustomCommand('Command 1', 'cmd1');
myWindow.addCustomCommand('Command 2', 'cmd2');
myWindow.addCustomCommand('Command 3', 'cmd3');
myWindow.refresh(); // This call is important, it's what actually calls makeCommandList & co.
The only issue now is that these commands do nothing when you click on them. To solve this, you'd use
setHandler from
Window_Selectable:
Code:
myWindow.setHandler('cmd1', () => console.log('Called 1!'));
myWindow.setHandler('cmd2', () => console.log('Called 2!'));
myWindow.setHandler('cmd3', () => console.log('Called 3!'));
And that's it. Encapsulation is preserved and we didn't put any game logic into the Window itself, only as a callback from the Scene via
setHandler.