feat: inventory ops
This commit is contained in:
parent
997ef691ca
commit
9d9f94a7cc
|
@ -121,7 +121,7 @@ class ItemProxy {
|
|||
|
||||
export default class Inventory extends Component {
|
||||
async updateMany(entities) {
|
||||
for (const [id, {cleared, given, qtyUpdated, swapped}] of entities) {
|
||||
for (const [id, {cleared, distributed, given, qtyUpdated, swapped}] of entities) {
|
||||
const instance = this.get(id);
|
||||
const {$$items, slots} = instance;
|
||||
if (cleared) {
|
||||
|
@ -173,6 +173,7 @@ export default class Inventory extends Component {
|
|||
instanceFromSchema() {
|
||||
const Instance = super.instanceFromSchema();
|
||||
const Component = this;
|
||||
const {ecs} = Component;
|
||||
return class InventoryInstance extends Instance {
|
||||
$$items = {};
|
||||
clear(slot) {
|
||||
|
@ -180,6 +181,56 @@ export default class Inventory extends Component {
|
|||
delete this.slots[slot];
|
||||
delete this.$$items[slot];
|
||||
}
|
||||
async distribute(slot, potentialDestinations) {
|
||||
const {slots} = this;
|
||||
if (!slots[slot]) {
|
||||
return;
|
||||
}
|
||||
const destinations = [];
|
||||
const given = [];
|
||||
const updated = [];
|
||||
for (const [entityId, destination] of potentialDestinations) {
|
||||
const {Inventory} = ecs.get(entityId);
|
||||
const {slots} = Inventory;
|
||||
if (!slots[destination]) {
|
||||
slots[destination] = {
|
||||
qty: 0,
|
||||
source: slots[slot].source,
|
||||
};
|
||||
this.$$items[destination] = new ItemProxy(Component, this, destination);
|
||||
await this.$$items[destination].load(slots[destination].source);
|
||||
destinations.push([entityId, destination]);
|
||||
given.push([entityId, destination]);
|
||||
}
|
||||
else if (slots[slot].source === slots[destination].source) {
|
||||
destinations.push([entityId, destination]);
|
||||
updated.push([entityId, destination, slots[destination].qty]);
|
||||
}
|
||||
}
|
||||
const {qty} = slots[slot];
|
||||
slots[slot].qty = 0;
|
||||
for (let i = 0; i < qty; ++i) {
|
||||
const [entityId, destination] = destinations[i % destinations.length];
|
||||
const {Inventory} = ecs.get(entityId);
|
||||
const {slots} = Inventory;
|
||||
slots[destination].qty += 1;
|
||||
}
|
||||
if (!destinations.find(([entityId, destination]) => {
|
||||
return entityId == this.entity && destination === slot;
|
||||
})) {
|
||||
this.clear(slot);
|
||||
}
|
||||
for (const [entityId, destination] of given) {
|
||||
const {Inventory} = ecs.get(entityId);
|
||||
const {slots} = Inventory;
|
||||
Component.markChange(entityId, 'given', {[destination]: {qty: slots[destination].qty, source: slots[destination].source}});
|
||||
}
|
||||
for (const [entityId, destination, qty] of updated) {
|
||||
const {Inventory} = ecs.get(entityId);
|
||||
const {slots} = Inventory;
|
||||
Component.markChange(entityId, 'qtyUpdated', {[destination]: slots[destination].qty - qty});
|
||||
}
|
||||
}
|
||||
item(slot) {
|
||||
return this.$$items[slot];
|
||||
}
|
||||
|
@ -265,7 +316,7 @@ export default class Inventory extends Component {
|
|||
value: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
quantity: {type: 'uint16'},
|
||||
qty: {type: 'uint16'},
|
||||
source: {type: 'string'},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -11,6 +11,8 @@ export default function Grid({
|
|||
highlighted,
|
||||
label,
|
||||
onSlotMouseDown,
|
||||
onSlotMouseMove,
|
||||
onSlotMouseUp,
|
||||
slots,
|
||||
}) {
|
||||
const Slots = slots.map((slot, i) => (
|
||||
|
@ -28,10 +30,15 @@ export default function Grid({
|
|||
<Slot
|
||||
icon={slot?.icon}
|
||||
onMouseDown={(event) => {
|
||||
onSlotMouseDown(i)
|
||||
onSlotMouseDown?.(i, event)
|
||||
event.stopPropagation();
|
||||
}}
|
||||
onMouseMove={(event) => {
|
||||
onSlotMouseMove?.(i, event)
|
||||
event.stopPropagation();
|
||||
}}
|
||||
onMouseUp={(event) => {
|
||||
onSlotMouseUp?.(i, event)
|
||||
event.stopPropagation();
|
||||
}}
|
||||
onDragStart={(event) => {
|
||||
|
|
|
@ -10,10 +10,9 @@ import Grid from './grid.jsx';
|
|||
*/
|
||||
function Hotbar({
|
||||
active,
|
||||
highlighted,
|
||||
hotbarIsHidden,
|
||||
onSlotMouseDown,
|
||||
slots,
|
||||
...rest
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
|
@ -35,10 +34,9 @@ function Hotbar({
|
|||
active={active}
|
||||
color="rgba(02, 02, 57, 0.6)"
|
||||
columns={10}
|
||||
highlighted={highlighted}
|
||||
label={slots[active] && slots[active].label}
|
||||
onSlotMouseDown={onSlotMouseDown}
|
||||
slots={slots}
|
||||
{...rest}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -11,6 +11,7 @@ export default function Slot({
|
|||
onDragStart,
|
||||
onDrop,
|
||||
onMouseDown,
|
||||
onMouseMove,
|
||||
onMouseUp,
|
||||
qty = 1,
|
||||
}) {
|
||||
|
@ -27,6 +28,7 @@ export default function Slot({
|
|||
event.preventDefault();
|
||||
}}
|
||||
onMouseDown={onMouseDown}
|
||||
onMouseMove={onMouseMove}
|
||||
onMouseUp={onMouseUp}
|
||||
>
|
||||
<div
|
||||
|
|
|
@ -45,6 +45,8 @@ function Ui({disconnected}) {
|
|||
const ecsRef = useEcs();
|
||||
const [showDisconnected, setShowDisconnected] = useState(false);
|
||||
const [bufferSlot, setBufferSlot] = useState();
|
||||
const hadBufferSlot = useRef();
|
||||
const distributing = useRef(new Map());
|
||||
const [devtoolsIsOpen, setDevtoolsIsOpen] = useState(false);
|
||||
const ratio = (RESOLUTION.x * (devtoolsIsOpen ? 2 : 1)) / RESOLUTION.y;
|
||||
const [camera, setCamera] = useState({x: 0, y: 0});
|
||||
|
@ -223,7 +225,7 @@ function Ui({disconnected}) {
|
|||
});
|
||||
}
|
||||
});
|
||||
}, [client, keepHotbarOpen, setDebug]);
|
||||
}, [client, keepHotbarOpen, mainEntityRef, setDebug]);
|
||||
const onEcsChangePacket = useCallback(() => {
|
||||
mainEntityRef.current = undefined;
|
||||
monopolizers.current = [];
|
||||
|
@ -390,7 +392,7 @@ function Ui({disconnected}) {
|
|||
mainEntityRef,
|
||||
scale,
|
||||
]);
|
||||
const hotbarOnSlotMouseDown = useCallback((i) => {
|
||||
const hotbarOnSlotMouseDown = useCallback((i, event) => {
|
||||
keepHotbarOpen();
|
||||
if (trading) {
|
||||
const index = losing.indexOf(i + 1);
|
||||
|
@ -403,12 +405,77 @@ function Ui({disconnected}) {
|
|||
setLosing([...losing]);
|
||||
}
|
||||
else {
|
||||
client.send({
|
||||
type: 'Action',
|
||||
payload: {type: 'swapSlots', value: [0, mainEntityRef.current, i + 1]},
|
||||
});
|
||||
hadBufferSlot.current = bufferSlot;
|
||||
switch (event.button) {
|
||||
case 0:
|
||||
if (bufferSlot) {
|
||||
// ...
|
||||
}
|
||||
else {
|
||||
client.send({
|
||||
type: 'Action',
|
||||
payload: {type: 'swapSlots', value: [0, mainEntityRef.current, i + 1]},
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
client.send({
|
||||
type: 'Action',
|
||||
payload: {
|
||||
type: 'distribute',
|
||||
value: [
|
||||
i + 1,
|
||||
[
|
||||
[mainEntityRef.current, 0],
|
||||
[mainEntityRef.current, i + 1],
|
||||
],
|
||||
],
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, [client, keepHotbarOpen, losing, mainEntityRef, trading]);
|
||||
}, [bufferSlot, client, keepHotbarOpen, losing, mainEntityRef, trading]);
|
||||
const hotbarOnSlotMouseMove = useCallback((i) => {
|
||||
if (hadBufferSlot.current) {
|
||||
distributing.current.set([mainEntityRef.current, i + 1].join(':'), true);
|
||||
}
|
||||
}, [mainEntityRef]);
|
||||
const hotbarOnSlotMouseUp = useCallback((i, event) => {
|
||||
keepHotbarOpen();
|
||||
if (trading) {
|
||||
// ...
|
||||
}
|
||||
else {
|
||||
switch (event.button) {
|
||||
case 0:
|
||||
if (distributing.current.size > 0) {
|
||||
client.send({
|
||||
type: 'Action',
|
||||
payload: {
|
||||
type: 'distribute',
|
||||
value: [
|
||||
0,
|
||||
Array.from(distributing.current.keys()).map((idAndSlot) => idAndSlot.split(':')),
|
||||
],
|
||||
},
|
||||
});
|
||||
distributing.current.clear();
|
||||
}
|
||||
else if (hadBufferSlot.current) {
|
||||
client.send({
|
||||
type: 'Action',
|
||||
payload: {type: 'swapSlots', value: [0, mainEntityRef.current, i + 1]},
|
||||
});
|
||||
}
|
||||
else {
|
||||
// ...
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
hadBufferSlot.current = undefined;
|
||||
}, [client, keepHotbarOpen, mainEntityRef, trading]);
|
||||
const bagOnSlotMouseDown = useCallback((i) => {
|
||||
if (trading) {
|
||||
const index = losing.indexOf(i + 11);
|
||||
|
@ -574,6 +641,8 @@ function Ui({disconnected}) {
|
|||
highlighted={trading && losing.filter((i) => i < 11).map((i) => i - 1)}
|
||||
hotbarIsHidden={hotbarIsHidden}
|
||||
onSlotMouseDown={hotbarOnSlotMouseDown}
|
||||
onSlotMouseMove={hotbarOnSlotMouseMove}
|
||||
onSlotMouseUp={hotbarOnSlotMouseUp}
|
||||
slots={hotbarSlots}
|
||||
/>
|
||||
<Bag
|
||||
|
|
|
@ -260,6 +260,13 @@ export default class Engine {
|
|||
Wallet.gold += earn;
|
||||
break;
|
||||
}
|
||||
case 'distribute': {
|
||||
if (!Controlled.locked) {
|
||||
const [slot, destinations] = payload.value;
|
||||
Inventory.distribute(slot, destinations);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'swapSlots': {
|
||||
if (!Controlled.locked) {
|
||||
const [l, other, r] = payload.value;
|
||||
|
|
Loading…
Reference in New Issue
Block a user