Skip to content

Commit

Permalink
Switch to useEvent
Browse files Browse the repository at this point in the history
This is mostly for clarity of locating event-driven reactions
  • Loading branch information
tiliv committed Jun 2, 2024
1 parent 10c9d9b commit cf528d0
Showing 1 changed file with 94 additions and 124 deletions.
218 changes: 94 additions & 124 deletions src/hooks/useInventory.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useState, useEffect, useCallback, useRef } from 'react';

import useSave from './useSave';
import useEvent from './useEvent';

const CATEGORIES = [
'hair',
Expand Down Expand Up @@ -50,18 +51,19 @@ export default function useInventory(subject, {
[`${subject}/log`]: [log, setLog],
});

useEffect(() => {
stats.current = { name, hp, strength, defense, speed, gold };
}, [name, hp, strength, defense, speed, gold]);

const addLog = useCallback(function(msg) {
setLog((log) => [msg, ...log]);
}, []);

const buy = useBuy({ subject, setGold, addLog });
const sell = useSell({ subject, setGold, addLog });
const equip = useEquip({ subject, inventory, setEquipment, setStrength, setDefense });
const acquire = useAcquire({ subject, setInventory, addLog });
const drop = useDrop({ subject, setInventory });

useSleep({ subject, hp, setHp, addLog });

const sleep = useSleep({ subject, setHp, addLog });
const possesses = useCallback(function(kind, identifier) {
function findEquipped(slot, kind=null) {
return inventory[kind || slot].find(({ id, name }) => {
Expand All @@ -80,12 +82,8 @@ export default function useInventory(subject, {
}, [equipment, inventory]);

useEffect(() => {
stats.current = { name, hp, strength, defense, speed, gold };
}, [name, hp, strength, defense, speed, gold]);

useEffect(() => {
handlers.current = { buy, sell, equip, acquire, drop, possesses };
}, [buy, sell, equip, acquire, drop, possesses])
handlers.current = { buy, sell, equip, acquire, drop, sleep, possesses };
}, [buy, sell, equip, acquire, drop, sleep, possesses])

return {
stats,
Expand All @@ -96,169 +94,141 @@ export default function useInventory(subject, {


function useSell({ subject, setGold, addLog }) {
useEffect(() => {
const eventName = `Sell.${subject}`;
const sell = function({ detail: { kind, price, target, item } }) {
// console.log('Selling', item, 'for', price, 'to', target);
setGold((gold) => gold + price);
addLog(`Sold ${item.name} to ${target.name}.`);
setTimeout(() => {
const drop = new CustomEvent(`Drop.${subject}`, { detail: { kind, item } });
window.dispatchEvent(drop);
const acquire = new CustomEvent(`Acquire.${target.name}`, { detail: { kind, item } });
window.dispatchEvent(acquire);
}, 0);
}
window.addEventListener(eventName, sell);
return () => window.removeEventListener(eventName, sell);
const sellHandler = useCallback(({ detail: { kind, price, target, item } }) => {
setGold((gold) => gold + price);
addLog(`Sold ${item.name} to ${target.name}.`);
setTimeout(() => {
const drop = new CustomEvent(`Drop.${subject}`, { detail: { kind, item } });
window.dispatchEvent(drop);
const acquire = new CustomEvent(`Acquire.${target.name}`, { detail: { kind, item } });
window.dispatchEvent(acquire);
}, 0);
}, [subject]);
useEvent(`Sell.${subject}`, sellHandler);

const sell = useCallback(function(kind, price, item, target) {
const sellTrigger = useCallback(function(kind, price, item, target) {
const event = new CustomEvent(`Sell.${subject}`, { detail: { kind, price, target, item } });
window.dispatchEvent(event);
}, [subject]);

return sell;
return sellTrigger;
};


function useBuy({ subject, setGold, addLog }) {
useEffect(() => {
const eventName = `Buy.${subject}`;
const buy = function({ detail: { kind, price, target, item } }) {
setGold((gold) => {
if (gold + price < 0) return gold;
addLog(`Bought ${item.name} from ${target.name}.`);
setTimeout(() => {
const acquire = new CustomEvent(`Acquire.${subject}`, { detail: { kind, item } });
window.dispatchEvent(acquire);
}, 0);
return gold + price;
});
};
window.addEventListener(eventName, buy);
return () => window.removeEventListener(eventName, buy);
const buyHandler = useCallback(({ detail: { kind, price, target, item } }) => {
setGold((gold) => {
if (gold + price < 0) return gold;
addLog(`Bought ${item.name} from ${target.name}.`);
setTimeout(() => {
const acquire = new CustomEvent(`Acquire.${subject}`, { detail: { kind, item } });
window.dispatchEvent(acquire);
}, 0);
return gold + price;
});
}, [subject]);
useEvent(`Buy.${subject}`, buyHandler);

const buy = useCallback(function(kind, price, item, target) {
const buyTrigger = useCallback(function(kind, price, item, target) {
const event = new CustomEvent(`Buy.${subject}`, { detail: { kind, price, target, item } });
window.dispatchEvent(event);
}, [subject]);

return buy;
return buyTrigger;
}


function useAcquire({ subject, setInventory }) {
// Respond to 'Acquire' event, either chained from a 'Buy' or triggered directly
useEffect(() => {
const eventName = `Acquire.${subject}`;
const acquire = function({ detail: { kind, item } }) {
setInventory((inventory) => {
const existing = inventory[kind] || [];
const maxId = existing.reduce(
(max, { id }) => Math.max(max, id),
0
);
return {
...inventory,
[kind]: [...existing, { ...item, id: maxId + 1 }],
}
});
}
window.addEventListener(eventName, acquire);
return () => window.removeEventListener(eventName, acquire);
}, [subject]);
const acquireHandler = useCallback(function({ detail: { kind, item } }) {
setInventory((inventory) => {
const existing = inventory[kind] || [];
const maxId = existing.reduce(
(max, { id }) => Math.max(max, id),
0
);
return {
...inventory,
[kind]: [...existing, { ...item, id: maxId + 1 }],
}
});
}, []);
useEvent(`Acquire.${subject}`, acquireHandler);

const acquire = useCallback(function(kind, item) {
const acquireTrigger = useCallback(function(kind, item) {
const event = new CustomEvent(`Acquire.${subject}`, { detail: { kind, item } });
window.dispatchEvent(event);
}, [subject]);

return acquire;
return acquireTrigger;
}


function useDrop({ subject, setInventory }) {
useEffect(() => {
const eventName = `Drop.${subject}`;
const drop = function({ detail: { kind, item } }) {
// console.log('Dropping', item, 'from', kind);
setInventory((inventory) => {
const existing = inventory[kind] || [];
return {
...inventory,
[kind]: existing.filter(({ id }) => id !== item.id),
};
});
}
window.addEventListener(eventName, drop);
return () => window.removeEventListener(eventName, drop);
}, [subject]);
const dropHandler = useCallback(function({ detail: { kind, item } }) {
setInventory((inventory) => {
const existing = inventory[kind] || [];
return {
...inventory,
[kind]: existing.filter(({ id }) => id !== item.id),
};
});
}, []);
useEvent(`Drop.${subject}`, dropHandler);

const drop = useCallback(function(kind, item) {
const dropTrigger = useCallback(function(kind, item) {
const event = new CustomEvent(`Drop.${subject}`, { detail: { kind, item } });
window.dispatchEvent(event);
}, [subject]);

return drop;
return dropTrigger;
}


function useEquip({ subject, inventory, setEquipment, setStrength, setDefense }) {
// Respond to 'Equip' event
useEffect(() => {
const eventName = `Equip.${subject}`;
const handler = function({ detail: { kind, id } }) {
const type = kind.startsWith('ring') ? 'ring' : kind;
const equipHandler = useCallback(function({ detail: { kind, id } }) {
const type = kind.startsWith('ring') ? 'ring' : kind;
const {
stats: { A=0, D=0 }={},
} = inventory[type].find(({ id: itemId }) => itemId === id) || {};
setEquipment((equipment) => {
const {
stats: { A=0, D=0 }={},
} = inventory[type].find(({ id: itemId }) => itemId === id) || {};
setEquipment((equipment) => {
const {
stats: { A: priorA=0, D: priorD=0 }={},
} = inventory[type].find(({ id: itemId }) => itemId === equipment[kind]) || {};
const newEquipment = { ...equipment, [kind]: id };
setStrength((strength) => strength + A - priorA);
setDefense((defense) => defense + D - priorD);
return newEquipment;
});
};
window.addEventListener(eventName, handler);
return () => window.removeEventListener(eventName, handler);
}, [subject, inventory]);

const equip = useCallback(function(kind, id) {
stats: { A: priorA=0, D: priorD=0 }={},
} = inventory[type].find(({ id: itemId }) => itemId === equipment[kind]) || {};
const newEquipment = { ...equipment, [kind]: id };
setStrength((strength) => strength + A - priorA);
setDefense((defense) => defense + D - priorD);
return newEquipment;
});
}, [inventory]);
useEvent(`Equip.${subject}`, equipHandler);

const equipTrigger = useCallback(function(kind, id) {
const event = new CustomEvent(`Equip.${subject}`, { detail: { kind, id } });
window.dispatchEvent(event);
}, [subject]);

return equip;
return equipTrigger;
}


function useSleep({ subject, hp, setHp, addLog }) {
useEffect(() => {
const eventName = `Sleep.${subject}`;
const handler = function({ detail: { quality } }) {
setHp((hp) => {
const newHp = Math.max(hp, quality);
if (hp >= quality) {
addLog(`Slept, but you feel about the same.`)
} else {
addLog(`Slept well, and healed to ${quality}.`);
}
return newHp;
});
};
window.addEventListener(eventName, handler);
return () => window.removeEventListener(eventName, handler);
}, [subject]);
function useSleep({ subject, setHp, addLog }) {
const sleepHandler = useCallback(function({ detail: { quality } }) {
setHp((hp) => {
const newHp = Math.max(hp, quality);
if (hp >= quality) {
addLog(`Slept, but you feel about the same.`)
} else {
addLog(`Slept well, and healed to ${quality}.`);
}
return newHp;
});
}, []);
useEvent(`Sleep.${subject}`, sleepHandler);

const sleep = useCallback(function(quality) {
const sleepTrigger = useCallback(function(quality) {
const event = new CustomEvent(`Sleep.${subject}`, { detail: { quality } });
window.dispatchEvent(event);
}, [subject]);

return sleep;
return sleepTrigger;
}

0 comments on commit cf528d0

Please sign in to comment.