Compare commits

..

6 Commits

Author SHA1 Message Date
cha0s
fe412e710e fix: item action 2024-06-24 06:19:11 -05:00
cha0s
f1b6a8b0d8 fix: consumption 2024-06-24 06:18:58 -05:00
cha0s
b630221f1f fix: key listener dependencies 2024-06-24 06:18:49 -05:00
cha0s
7af6b635bf fix: markup semantics 2024-06-24 05:34:02 -05:00
cha0s
cc8c78cb30 refactor: tidy 2024-06-24 05:02:13 -05:00
cha0s
3b08a87f39 chore: storybook 2024-06-24 05:00:24 -05:00
10 changed files with 41 additions and 36 deletions

View File

@ -2,7 +2,6 @@ import Schema from '@/ecs/schema.js';
export default function(Component) { export default function(Component) {
return class Inventory extends Component { return class Inventory extends Component {
insertMany(entities) { insertMany(entities) {
for (const [id, {slotChange}] of entities) { for (const [id, {slotChange}] of entities) {
if (slotChange) { if (slotChange) {
@ -22,7 +21,6 @@ export default function(Component) {
} }
return super.insertMany(entities); return super.insertMany(entities);
} }
mergeDiff(original, update) { mergeDiff(original, update) {
if (!update.slotChange) { if (!update.slotChange) {
return super.mergeDiff(original, update); return super.mergeDiff(original, update);
@ -57,6 +55,7 @@ export default function(Component) {
target[property] = value; target[property] = value;
if ('qty' === property && value <= 0) { if ('qty' === property && value <= 0) {
Component.markChange(instance.entity, 'slotChange', {[slot]: false}); Component.markChange(instance.entity, 'slotChange', {[slot]: false});
delete slots[slot];
} }
else { else {
Component.markChange(instance.entity, 'slotChange', {[slot]: {[property]: value}}); Component.markChange(instance.entity, 'slotChange', {[slot]: {[property]: value}});

View File

@ -234,16 +234,22 @@ export default class Engine {
break; break;
} }
case 'use': { case 'use': {
if (payload.value) { const item = Inventory.item(Wielder.activeSlot + 1);
const item = Inventory.item(Wielder.activeSlot + 1); if (item) {
this.server.readAsset(item.source + '/start.js') this.server.readAsset([
.then((response) => response.text()) item.source,
payload.value ? 'start.js' : 'stop.js',
].join('/'))
.then((response) => response.ok ? response.text() : '')
.then((code) => { .then((code) => {
Ticking.addTickingPromise( if (code) {
Script.tickingPromise(code, {item, wielder: entity}), Ticking.addTickingPromise(
); Script.tickingPromise(code, {item, wielder: entity}),
);
}
}); });
} }
break;
} }
} }
} }

View File

@ -6,16 +6,18 @@ import Slot from './slot.jsx';
*/ */
export default function Hotbar({active, onActivate, slots}) { export default function Hotbar({active, onActivate, slots}) {
const Slots = slots.map((slot, i) => ( const Slots = slots.map((slot, i) => (
<button <div
className={ className={
[styles.slotWrapper, active === i && styles.active] [styles.slotWrapper, active === i && styles.active]
.filter(Boolean).join(' ') .filter(Boolean).join(' ')
} }
onClick={() => onActivate(i)}
key={i} key={i}
> >
<Slot {...slot} /> <Slot
</button> onClick={() => onActivate(i)}
{...slot}
/>
</div>
)); ));
return ( return (
<div <div

View File

@ -11,7 +11,6 @@
} }
.slotWrapper { .slotWrapper {
background-color: transparent;
border: var(--border) solid #999999; border: var(--border) solid #999999;
box-sizing: border-box; box-sizing: border-box;
display: inline-block; display: inline-block;

View File

@ -3,9 +3,10 @@ import styles from './slot.module.css';
/** /**
* An inventory slot. Displays an item image and the quantity of the item if > 1. * An inventory slot. Displays an item image and the quantity of the item if > 1.
*/ */
export default function Slot({image, onClick, qty = 1}) { export default function Slot({source, onClick, qty = 1}) {
const image = source + '/icon.png';
return ( return (
<div <button
className={styles.slot} className={styles.slot}
onClick={onClick} onClick={onClick}
> >
@ -24,6 +25,6 @@ export default function Slot({image, onClick, qty = 1}) {
</span> </span>
)} )}
</div> </div>
</div> </button>
); );
} }

View File

@ -1,9 +1,11 @@
.slot { .slot {
--size: calc(var(--unit) * 50px); --size: calc(var(--unit) * 50px);
--space: calc(var(--unit) * 10px); --space: calc(var(--unit) * 10px);
background-color: transparent;
background-position: center; background-position: center;
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: contain; background-size: contain;
border: none;
display: inline-block; display: inline-block;
height: var(--size); height: var(--size);
image-rendering: pixelated; image-rendering: pixelated;

View File

@ -137,7 +137,7 @@ export default function Ui({disconnected}) {
}); });
} }
}); });
}); }, [client]);
usePacket('Tick', (payload) => { usePacket('Tick', (payload) => {
if (0 === Object.keys(payload.ecs).length) { if (0 === Object.keys(payload.ecs).length) {
return; return;
@ -154,13 +154,7 @@ export default function Ui({disconnected}) {
if (update.Inventory) { if (update.Inventory) {
const newHotbarSlots = emptySlots(); const newHotbarSlots = emptySlots();
for (let i = 1; i < 11; ++i) { for (let i = 1; i < 11; ++i) {
if (entity.Inventory.slots[i]) { newHotbarSlots[i - 1] = entity.Inventory.slots[i];
const {qty, source} = entity.Inventory.slots[i];
newHotbarSlots[i - 1] = {
image: source + '/icon.png',
qty,
};
}
} }
setHotbarSlots(newHotbarSlots); setHotbarSlots(newHotbarSlots);
} }
@ -186,7 +180,7 @@ export default function Ui({disconnected}) {
onActivate={(i) => { onActivate={(i) => {
client.send({ client.send({
type: 'Action', type: 'Action',
payload: {type: 'changeSlot', value: i}, payload: {type: 'changeSlot', value: i + 1},
}); });
}} }}
slots={hotbarSlots} slots={hotbarSlots}

View File

@ -1,6 +1,6 @@
import {useEffect, useRef, useState} from 'react'; import {useEffect, useRef, useState} from 'react';
import Dom from '@/components/dom.jsx'; import Dom from '@/react-components/dom.jsx';
import {RESOLUTION} from '@/constants.js'; import {RESOLUTION} from '@/constants.js';
function Decorator({children, style}) { function Decorator({children, style}) {
@ -26,6 +26,7 @@ function Decorator({children, style}) {
ref={ref} ref={ref}
style={{ style={{
backgroundColor: '#1099bb', backgroundColor: '#1099bb',
flexDirection: 'column',
opacity: 0 === scale ? 0 : 1, opacity: 0 === scale ? 0 : 1,
position: 'relative', position: 'relative',
height: `calc(${RESOLUTION.y}px * ${scale})`, height: `calc(${RESOLUTION.y}px * ${scale})`,

View File

@ -1,14 +1,12 @@
import {useArgs} from '@storybook/preview-api'; import {useArgs} from '@storybook/preview-api';
import {fn} from '@storybook/test'; import {fn} from '@storybook/test';
import Hotbar from '@/components/hotbar.jsx'; import Hotbar from '@/react-components/hotbar.jsx';
import DomDecorator from './dom-decorator.jsx'; import DomDecorator from './dom-decorator.jsx';
import potion from '/assets/potion.png?url';
const slots = Array(10).fill({}); const slots = Array(10).fill({});
slots[2] = {image: potion, qty: 24}; slots[2] = {qty: 24, source: '/assets/potion'};
export default { export default {
title: 'Dom/Inventory/Hotbar', title: 'Dom/Inventory/Hotbar',
@ -25,7 +23,12 @@ export default {
}; };
return Hotbar(); return Hotbar();
}, },
DomDecorator(), DomDecorator({
style: {
display: 'flex',
flexDirection: 'column',
},
}),
], ],
tags: ['autodocs'], tags: ['autodocs'],
args: { args: {

View File

@ -1,9 +1,7 @@
import Slot from '@/components/slot.jsx'; import Slot from '@/react-components/slot.jsx';
import DomDecorator from './dom-decorator.jsx'; import DomDecorator from './dom-decorator.jsx';
import potion from '/assets/potion.png?url';
export default { export default {
title: 'Dom/Inventory/Slot', title: 'Dom/Inventory/Slot',
component: Slot, component: Slot,
@ -33,7 +31,7 @@ export default {
}, },
}, },
args: { args: {
image: potion, source: '/assets/potion',
}, },
}; };