175 lines
4.7 KiB
JavaScript
175 lines
4.7 KiB
JavaScript
import Component from '@/ecs/component.js';
|
|
|
|
export default class Inventory extends Component {
|
|
insertMany(entities) {
|
|
for (const [id, {slotChange}] of entities) {
|
|
if (slotChange) {
|
|
const {slots} = this.get(id);
|
|
for (const slotIndex in slotChange) {
|
|
if (false === slotChange[slotIndex]) {
|
|
delete slots[slotIndex];
|
|
}
|
|
else {
|
|
slots[slotIndex] = {
|
|
...slots[slotIndex],
|
|
...slotChange[slotIndex],
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return super.insertMany(entities);
|
|
}
|
|
instanceFromSchema() {
|
|
const Instance = super.instanceFromSchema();
|
|
const Component = this;
|
|
return class InventoryInstance extends Instance {
|
|
$$items = {};
|
|
item(slot) {
|
|
return this.$$items[slot];
|
|
}
|
|
swapSlots(l, r) {
|
|
const {slots} = this;
|
|
const tmp = slots[l];
|
|
const change = {};
|
|
if (slots[r]) {
|
|
change[l] = slots[l] = slots[r];
|
|
}
|
|
else {
|
|
change[l] = false;
|
|
delete slots[l];
|
|
}
|
|
if (tmp) {
|
|
change[r] = slots[r] = tmp;
|
|
}
|
|
else {
|
|
change[r] = false;
|
|
delete slots[r];
|
|
}
|
|
Component.markChange(this.entity, 'slotChange', change);
|
|
}
|
|
}
|
|
}
|
|
async load(instance) {
|
|
const Component = this;
|
|
const {readAsset} = this.ecs;
|
|
const {slots} = instance;
|
|
class ItemProxy {
|
|
constructor(slot, json) {
|
|
this.json = json;
|
|
this.slot = slot;
|
|
}
|
|
project(position, direction) {
|
|
const {TileLayers: {layers: [layer]}} = Component.ecs.get(1);
|
|
const {projection} = this.json;
|
|
let startX = position.x;
|
|
let startY = position.y;
|
|
switch (direction) {
|
|
case 0:
|
|
startX += projection.distance[1];
|
|
startY -= projection.distance[0];
|
|
break;
|
|
case 1:
|
|
startX += projection.distance[0];
|
|
startY += projection.distance[1];
|
|
break;
|
|
case 2:
|
|
startX -= projection.distance[1];
|
|
startY += projection.distance[0];
|
|
break;
|
|
case 3:
|
|
startX -= projection.distance[0];
|
|
startY -= projection.distance[1];
|
|
break;
|
|
}
|
|
const projected = [];
|
|
for (const row in projection.grid) {
|
|
const columns = projection.grid[row];
|
|
for (const column in columns) {
|
|
const targeted = projection.grid[row][column];
|
|
if (targeted) {
|
|
let axe;
|
|
switch (direction) {
|
|
case 0:
|
|
axe = [column, row];
|
|
break;
|
|
case 1:
|
|
axe = [-row, column];
|
|
break;
|
|
case 2:
|
|
axe = [-column, -row];
|
|
break;
|
|
case 3:
|
|
axe = [row, -column];
|
|
break;
|
|
}
|
|
const x = startX + parseInt(axe[0]);
|
|
const y = startY + parseInt(axe[1]);
|
|
if (x < 0 || y < 0 || x >= layer.area.x || y >= layer.area.y) {
|
|
continue;
|
|
}
|
|
projected.push({x, y});
|
|
}
|
|
}
|
|
}
|
|
return projected;
|
|
}
|
|
get qty() {
|
|
return slots[this.slot].qty;
|
|
}
|
|
set qty(qty) {
|
|
if (qty <= 0) {
|
|
Component.markChange(instance.entity, 'slotChange', {[this.slot]: false});
|
|
delete slots[this.slot];
|
|
}
|
|
else {
|
|
slots[this.slot].qty = qty;
|
|
Component.markChange(instance.entity, 'slotChange', {[this.slot]: {qty}});
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const slot in slots) {
|
|
const chars = await readAsset([slots[slot].source, 'item.json'].join('/'))
|
|
const json = chars.byteLength > 0
|
|
? JSON.parse(
|
|
(new TextDecoder()).decode(chars),
|
|
)
|
|
: {};
|
|
instance.$$items[slot] = new ItemProxy(slots, json);
|
|
}
|
|
}
|
|
mergeDiff(original, update) {
|
|
if (!update.slotChange) {
|
|
return super.mergeDiff(original, update);
|
|
}
|
|
const slotChange = {
|
|
...original.slotChange,
|
|
};
|
|
for (const index in update.slotChange) {
|
|
if (false === update.slotChange[index]) {
|
|
slotChange[index] = false;
|
|
}
|
|
else {
|
|
slotChange[index] = {
|
|
...slotChange[index],
|
|
...update.slotChange[index],
|
|
};
|
|
}
|
|
}
|
|
return {slotChange};
|
|
}
|
|
static properties = {
|
|
slots: {
|
|
type: 'map',
|
|
value: {
|
|
type: 'object',
|
|
properties: {
|
|
quantity: {type: 'uint16'},
|
|
source: {type: 'string'},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
}
|