-
Notifications
You must be signed in to change notification settings - Fork 3
/
hotbar.js
203 lines (158 loc) · 5.91 KB
/
hotbar.js
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
'use strict';
const EventEmitter = require('events').EventEmitter;
const InventoryWindow = require('inventory-window');
const ever = require('ever');
module.exports = (game, opts) => {
if (game.isClient) {
return new InventoryHotbarClient(game, opts);
} else {
return new InventoryHotbarCommon(game, opts);
}
};
module.exports.pluginInfo = {
loadAfter: ['voxel-carry', 'voxel-registry', 'voxel-keys']
};
class InventoryHotbarCommon extends EventEmitter {
constructor(game, opts) {
super();
this.game = game;;
if (!opts) opts = {};
this.inventory = game.plugins.get('voxel-carry').inventory || opts.playerInventory; // TODO: proper error if voxel-carry missing
if (!this.inventory ) throw new Error('voxel-inventory-dialog requires "voxel-carry" plugin or playerInventory" set to inventory instance');
this.selectedIndex = 0;
}
enable() {
}
disable() {
}
give(itemPile){
return this.inventory.give(itemPile);
}
take(itemPile) {
return this.inventory.take(itemPile);
}
// take some items from the pile the player is currently holding
takeHeld() {
if (count === undefined) count = 1;
return this.inventory.takeAt(this.selectedIndex, count);
}
// completely replace held item pile
replaceHeld(itemPile) {
return this.inventory.set(this.selectedIndex, itemPile);
}
// get the pile of items the player is currently holding
held() {
return this.inventory.get(this.selectedIndex);
}
setSelectedIndex(x) {
this.selectedIndex = x;
}
}
class InventoryHotbarClient extends InventoryHotbarCommon {
constructor(game, opts) {
super(game, opts);
this.game = game;
this.keys = game.plugins.get('voxel-keys');
if (!this.keys) throw new Error('voxel-inventory-hotbar requires voxel-keys plugin');
this.wheelEnable = opts.wheelEnable !== undefined ? opts.wheelEnable : false; // enable scroll wheel to change slots?
this.wheelScale = opts.wheelScale !== undefined ? opts.wheelScale : 1.0; // mouse wheel scrolling sensitivity
const registry = game.plugins.get('voxel-registry');
const windowOpts = opts.windowOpts !== undefined ? opts.windowOpts : {};
if (!windowOpts.registry && registry) windowOpts.registry = registry;
if (!windowOpts.inventory) windowOpts.inventory = this.inventory;
if (windowOpts.inventorySize === undefined) windowOpts.inventorySize = opts.inventorySize;
if (windowOpts.inventorySize === undefined) windowOpts.inventorySize = this.inventory.size();
if (windowOpts.width === undefined) windowOpts.width = opts.width;
if (windowOpts.width === undefined) windowOpts.width = windowOpts.inventorySize; // default to one row
this.inventoryWindow = new InventoryWindow(windowOpts);
this.inventoryWindow.selectedIndex = 0;
//this.setSelectedIndex(0); // can't set this early; requires DOM
const container = this.inventoryWindow.createContainer();
// center at bottom of screen
container.style.bottom = '0px';
container.style.zIndex = 5;
container.style.width = '100%';
container.style.position = 'fixed';
container.style.float = '';
container.style.border = ''; // not tight around edges
const outerDiv = document.createElement('div');
outerDiv.style.width = '100%';
outerDiv.style.textAlign = 'center';
outerDiv.appendChild(container);
document.body.appendChild(outerDiv);
this.enable();
}
setSelectedIndex(x) {
event = {
oldIndex: this.selectedIndex,
newIndex:x,
cancelled:false,
};
this.emit('selectionChanging', event);
if (event.cancelled) return;
this.inventoryWindow.setSelected(x);
super.setSelectedIndex(x);
}
enable() {
this.inventoryWindow.container.style.visibility = '';
this.onSlots = {};
if (this.wheelEnable) {
ever(document.body).on('mousewheel', this.mousewheel = (ev) => { // TODO: also DOMScrollWheel for Firefox
console.log('mousewheel',ev);
let delta = ev.wheelDelta;
delta /= this.wheelScale;
delta = Math.floor(delta);
let newSlot = this.selectedIndex + delta;
function true_modulo(a, b) { return (a % b + b) % b; } // a %% b
newSlot = true_modulo(newSlot, this.inventoryWindow.width);
console.log(newSlot);
this.setSelectedIndex(newSlot);
});
}
if (this.game.shell || this.game.buttons.bindings) { // configurable bindings available
for (let slot = 0; slot <= 9; ++slot) {
// key numeric 1 is slot 0th, 2 is 1st, .. 0 is last
let key;
if (slot === 9) {
key = '0';
} else {
key = ''+(slot + 1);
}
// human-readable keybinding name (1-based)
const slotName = 'slot' + (slot + 1);
if (this.game.shell) {
this.game.shell.bind(slotName, key);
} else if (this.game.buttons.bindings) {
this.game.buttons.bindings[key] = slotName;
}
this.keys.down.on(slotName, this.onSlots[key] = () => {
this.setSelectedIndex(slot);
});
}
} else { // fallback kb-controls support
throw new Error('fallback kb-controls support removed');
}
super.enable();
}
disable() {
this.inventoryWindow.container.style.visibility = 'hidden';
if (this.mousewheel !== undefined) ever(document.body).removeListener('mousewheel', this.mousewheel);
if (this.game.shell) {
for (let key = 1; key <= 10; ++key) {
this.game.shell.unbind('slot' + key);
this.keys.down.removeListener('slot' + key, this.onSlots[key - 1]);
}
} else if (this.game.buttons.bindings) {
for (let key = 1; key <= 10; ++key) {
delete this.game.buttons.bindings[key - 1];
this.keys.down.removeListener('slot' + key, this.onSlots[key - 1]);
}
} else {
ever(document.body).removeListener('keydown', this.keydown);
}
super.disable();
}
refresh() {
this.inventoryWindow.refresh();
}
}