refactor: much better item UI handling
This commit is contained in:
parent
ae19826040
commit
20837ea2f0
22
client/ui/hooks/use-inventory-slice.js
Normal file
22
client/ui/hooks/use-inventory-slice.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
// 3rd party.
|
||||
import * as I from 'immutable';
|
||||
import React, {useState} from 'react';
|
||||
// 1st party.
|
||||
import {useEvent} from './use-event';
|
||||
|
||||
export function useInventorySlice(selfEntity, start, end) {
|
||||
const [items, setItems] = useState(I.List());
|
||||
useEvent(selfEntity, 'inventoryChanged', () => {
|
||||
setItems(items.withMutations((items) => {
|
||||
for (let i = start; i < end; ++i) {
|
||||
const item = selfEntity.itemInSlot(i);
|
||||
items.set(i, item ? item : undefined);
|
||||
}
|
||||
}));
|
||||
});
|
||||
const slice = [];
|
||||
for (let i = start; i < end; ++i) {
|
||||
slice.push(items.get(i));
|
||||
}
|
||||
return slice;
|
||||
}
|
|
@ -1,51 +1,32 @@
|
|||
// 3rd party.
|
||||
import classnames from 'classnames';
|
||||
import * as I from 'immutable';
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import React from 'react';
|
||||
// 2nd party.
|
||||
import {compose} from '@avocado/core';
|
||||
import contempo from 'contempo';
|
||||
// 1st party.
|
||||
import {useEvent} from '../hooks/use-event';
|
||||
import {usePropertyChange} from '../hooks/use-property-change';
|
||||
import {useInventorySlice} from '../hooks/use-inventory-slice';
|
||||
|
||||
import ItemSlot from './item-slot';
|
||||
|
||||
const decorate = compose(
|
||||
contempo(require('./hotbar.raw.scss').default),
|
||||
);
|
||||
|
||||
const HotbarComponent = ({app}) => {
|
||||
const selfEntity = usePropertyChange(app, 'selfEntity');
|
||||
const activeSlotIndex = usePropertyChange(selfEntity, 'activeSlotIndex');
|
||||
const [items, setItems] = useState(I.List());
|
||||
useEvent(selfEntity, 'inventoryChanged', () => {
|
||||
setItems(items.withMutations((items) => {
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
const item = selfEntity.itemInSlot(i);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
if (!items.has(i)) {
|
||||
items.set(i, I.Map());
|
||||
}
|
||||
items.set(i, items.get(i).withMutations((listItem) => {
|
||||
listItem.set('backgroundImage', item.imageForSlot());
|
||||
listItem.set('qty', item.qty);
|
||||
}));
|
||||
}
|
||||
}));
|
||||
});
|
||||
const HotbarComponent = ({selfEntity}) => {
|
||||
const hotkeyForSlot = (index) => {
|
||||
return (index + 1) % 10;
|
||||
}
|
||||
const slots = [];
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
const slot = <ItemSlot
|
||||
const activeSlotIndex = usePropertyChange(selfEntity, 'activeSlotIndex');
|
||||
const itemSlice = useInventorySlice(selfEntity, 0, 10);
|
||||
const itemSlots = itemSlice.map((item, i) => {
|
||||
return <ItemSlot
|
||||
key={i}
|
||||
item={item}
|
||||
className={classnames(
|
||||
activeSlotIndex === i ? 'active' : '',
|
||||
)}
|
||||
item={items.get(i)}
|
||||
key={i}
|
||||
onClick={(event) => {
|
||||
if (selfEntity) {
|
||||
selfEntity.activeSlotIndex = i;
|
||||
|
@ -57,13 +38,12 @@ const HotbarComponent = ({app}) => {
|
|||
>
|
||||
<div className="hotbar-key">{hotkeyForSlot(i)}</div>
|
||||
</ItemSlot>;
|
||||
slots.push(slot);
|
||||
}
|
||||
});
|
||||
return <div
|
||||
className="hotbar unselectable"
|
||||
>
|
||||
<div className="hotbar-inner">
|
||||
{slots}
|
||||
{itemSlots}
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import {compose} from '@avocado/core';
|
|||
import contempo from 'contempo';
|
||||
// 1st party.
|
||||
import {useEvent} from '../hooks/use-event';
|
||||
import {usePropertyChange} from '../hooks/use-property-change';
|
||||
import QuickStatus from './quick-status';
|
||||
import Hotbar from './hotbar';
|
||||
import Inventory from './inventory';
|
||||
|
@ -17,6 +18,7 @@ const decorate = compose(
|
|||
|
||||
const MenuComponent = ({app}) => {
|
||||
const [opened, setOpened] = useState(false);
|
||||
const selfEntity = usePropertyChange(app, 'selfEntity');
|
||||
useEvent(app, 'isMenuOpenedChanged', (_, isOpened) => {
|
||||
setOpened(isOpened);
|
||||
});
|
||||
|
@ -25,10 +27,10 @@ const MenuComponent = ({app}) => {
|
|||
'menu-inner',
|
||||
opened ? 'open' : '',
|
||||
)}>
|
||||
<Inventory app={app} />
|
||||
<Inventory selfEntity={selfEntity} />
|
||||
<QuickStatus app={app} />
|
||||
<WorldTime worldTime={app.worldTime} />
|
||||
<Hotbar app={app} />
|
||||
<Hotbar selfEntity={selfEntity} />
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
|
|
@ -1,24 +1,25 @@
|
|||
// 3rd party.
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import React from 'react';
|
||||
// 2nd party.
|
||||
import {compose} from '@avocado/core';
|
||||
import contempo from 'contempo';
|
||||
// 1st party.
|
||||
import {useInventorySlice} from '../hooks/use-inventory-slice';
|
||||
import ItemSlot from './item-slot';
|
||||
|
||||
const decorate = compose(
|
||||
contempo(require('./inventory.raw.scss').default),
|
||||
);
|
||||
|
||||
const InventoryComponent = () => {
|
||||
const bagSlots = [];
|
||||
for (let i = 0; i < 40; ++i) {
|
||||
bagSlots.push(<ItemSlot key={i} />);
|
||||
}
|
||||
const equipmentSlots = [];
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
equipmentSlots.push(<ItemSlot key={i} />);
|
||||
}
|
||||
const InventoryComponent = ({selfEntity}) => {
|
||||
const bagSlice = useInventorySlice(selfEntity, 10, 50);
|
||||
const bagSlots = bagSlice.map((item, i) => {
|
||||
return <ItemSlot key={i} item={item} />;
|
||||
});
|
||||
const equipmentSlice = useInventorySlice(selfEntity, 50, 54);
|
||||
const equipmentSlots = equipmentSlice.map((item, i) => {
|
||||
return <ItemSlot key={i} item={item} />;
|
||||
});
|
||||
return <div className="inventory unselectable">
|
||||
<div className="inventory-inner">
|
||||
<div className="bag">{bagSlots}</div>
|
||||
|
|
|
@ -4,6 +4,8 @@ import React, {useEffect, useState} from 'react';
|
|||
// 2nd party.
|
||||
import {compose} from '@avocado/core';
|
||||
import contempo from 'contempo';
|
||||
// 1st party.
|
||||
import {useEvent} from '../hooks/use-event';
|
||||
|
||||
const decorate = compose(
|
||||
contempo(require('./item-slot.raw.scss').default),
|
||||
|
@ -11,15 +13,15 @@ const decorate = compose(
|
|||
|
||||
const ItemSlotComponent = (props) => {
|
||||
const {children, className, item, ...rest} = props;
|
||||
const [qty, setQty] = useState(undefined);
|
||||
useEvent(item, 'qtyChanged', (_, qty) => setQty(item.qty));
|
||||
let backgroundImageUri;
|
||||
let qty;
|
||||
let qtyClass;
|
||||
if (item) {
|
||||
const backgroundImage = item.get('backgroundImage');
|
||||
const backgroundImage = item.imageForSlot();
|
||||
if (backgroundImage) {
|
||||
backgroundImageUri = backgroundImage.uri;
|
||||
}
|
||||
qty = item.get('qty');
|
||||
if (qty > 9999) {
|
||||
qtyClass = 'e4';
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user