From 5fe70ee6bc5380c556169756a375956799093604 Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Tue, 26 Mar 2024 13:07:37 +0100 Subject: [PATCH 1/1] merge manual and computed state --- .../js/components/tracker/AutoTracking.js | 10 ++-- resources/js/components/tracker/Equipment.js | 4 -- resources/js/components/tracker/Map.js | 40 ++++++------- resources/js/components/tracker/ToggleIcon.js | 6 +- resources/js/components/tracker/index.js | 6 +- resources/js/helpers/tracker.js | 56 +++++++++++++++++-- resources/js/hooks/tracker.js | 10 +++- resources/sass/tracker.scss | 11 ++++ 8 files changed, 102 insertions(+), 41 deletions(-) diff --git a/resources/js/components/tracker/AutoTracking.js b/resources/js/components/tracker/AutoTracking.js index 8528856..dfa1972 100644 --- a/resources/js/components/tracker/AutoTracking.js +++ b/resources/js/components/tracker/AutoTracking.js @@ -11,7 +11,7 @@ import { WRAM_ADDR, buildPrizeMap, } from '../../helpers/alttp-ram'; -import { computeState, mergeStates } from '../../helpers/tracker'; +import { computeState } from '../../helpers/tracker'; import { useSNES } from '../../hooks/snes'; import { useTracker } from '../../hooks/tracker'; @@ -26,7 +26,7 @@ const AutoTracking = () => { sock, status, } = useSNES(); - const { config, setState } = useTracker(); + const { config, setAutoState } = useTracker(); const { t } = useTranslation(); const enable = React.useCallback(() => { @@ -74,8 +74,8 @@ const AutoTracking = () => { const saveStart = WRAM_ADDR.SAVE_DATA; const saveSize = SRAM_ADDR.INV_END; sock.current.readWRAM(saveStart, saveSize, (data) => { - const computed = computeState(data, prizeMap); - setState(s => mergeStates(config, s, computed)); + const computed = computeState(config, data, prizeMap); + setAutoState(computed); }); }; const fetchPrizes = () => { @@ -118,7 +118,7 @@ const AutoTracking = () => { return 'tracking'; }, [enabled, status]); - return
+ return
{['disconnected', 'error', 'no-device'].includes(statusMsg) ? { - const { state } = useTracker(); - return
diff --git a/resources/js/components/tracker/Map.js b/resources/js/components/tracker/Map.js index cfae29c..b77612e 100644 --- a/resources/js/components/tracker/Map.js +++ b/resources/js/components/tracker/Map.js @@ -686,7 +686,7 @@ const makeBackground = (src, level) => { }; const Map = () => { - const { dungeons, setState, state } = useTracker(); + const { dungeons, setManualState, state } = useTracker(); const mapDungeon = React.useCallback(dungeon => { const definition = dungeons.find(d => d.id === dungeon.id); @@ -701,51 +701,51 @@ const Map = () => { remaining, handlePrimary: () => { if (getDungeonRemainingItems(state, definition)) { - setState(addDungeonCheck(definition)); + setManualState(addDungeonCheck(definition)); } else if ( !hasDungeonBoss(state, definition) || !hasDungeonPrize(state, definition) ) { if (definition.boss) { - setState(setBossDefeated(definition, true)); + setManualState(setBossDefeated(definition, true)); } if (definition.prize) { - setState(setPrizeAcquired(definition, true)); + setManualState(setPrizeAcquired(definition, true)); } } else { - setState(resetDungeonChecks(definition)); + setManualState(resetDungeonChecks(definition)); if (definition.boss) { - setState(setBossDefeated(definition, false)); + setManualState(setBossDefeated(definition, false)); } if (definition.prize) { - setState(setPrizeAcquired(definition, false)); + setManualState(setPrizeAcquired(definition, false)); } } }, handleSecondary: () => { if (isDungeonCleared(state, definition)) { if (definition.items) { - setState(removeDungeonCheck(definition)); + setManualState(removeDungeonCheck(definition)); } if (definition.boss) { - setState(setBossDefeated(definition, false)); + setManualState(setBossDefeated(definition, false)); } if (definition.prize) { - setState(setPrizeAcquired(definition, false)); + setManualState(setPrizeAcquired(definition, false)); } } else if (getDungeonClearedItems(state, definition)) { - setState(removeDungeonCheck(definition)); + setManualState(removeDungeonCheck(definition)); } else { - setState(completeDungeonChecks(definition)); + setManualState(completeDungeonChecks(definition)); if (definition.boss) { - setState(setBossDefeated(definition, true)); + setManualState(setBossDefeated(definition, true)); } if (definition.prize) { - setState(setPrizeAcquired(definition, true)); + setManualState(setPrizeAcquired(definition, true)); } } }, }; - }, [dungeons, setState, state]); + }, [dungeons, setManualState, state]); const mapLocation = React.useCallback(loc => { const remaining = countRemainingLocations(state, loc.checks); @@ -759,20 +759,20 @@ const Map = () => { status, handlePrimary: () => { if (remaining) { - setState(clearAll(loc.checks)); + setManualState(clearAll(loc.checks)); } else { - setState(unclearAll(loc.checks)); + setManualState(unclearAll(loc.checks)); } }, handleSecondary: () => { if (remaining) { - setState(clearAll(loc.checks)); + setManualState(clearAll(loc.checks)); } else { - setState(unclearAll(loc.checks)); + setManualState(unclearAll(loc.checks)); } }, }; - }, [setState, state]); + }, [setManualState, state]); const lwDungeons = React.useMemo(() => LW_DUNGEONS.map(mapDungeon), [mapDungeon]); const lwLocations = React.useMemo(() => LW_LOCATIONS.map(mapLocation), [mapLocation]); diff --git a/resources/js/components/tracker/ToggleIcon.js b/resources/js/components/tracker/ToggleIcon.js index f7cc074..da1a181 100644 --- a/resources/js/components/tracker/ToggleIcon.js +++ b/resources/js/components/tracker/ToggleIcon.js @@ -19,7 +19,7 @@ import { import { useTracker } from '../../hooks/tracker'; const ToggleIcon = ({ controller, className, icons }) => { - const { state, setState } = useTracker(); + const { setManualState, state } = useTracker(); const activeController = controller || ToggleIcon.nullController; const active = activeController.getActive(state, icons); const defaultIcon = activeController.getDefault(state, icons); @@ -35,12 +35,12 @@ const ToggleIcon = ({ controller, className, icons }) => { return { - activeController.handlePrimary(state, setState, icons); + activeController.handlePrimary(state, setManualState, icons); e.preventDefault(); e.stopPropagation(); }} onContextMenu={(e) => { - activeController.handleSecondary(state, setState, icons); + activeController.handleSecondary(state, setManualState, icons); e.preventDefault(); e.stopPropagation(); }} diff --git a/resources/js/components/tracker/index.js b/resources/js/components/tracker/index.js index 9cf88b4..ea09a22 100644 --- a/resources/js/components/tracker/index.js +++ b/resources/js/components/tracker/index.js @@ -11,8 +11,10 @@ const Tracker = () => {
- - +
+ + +
diff --git a/resources/js/helpers/tracker.js b/resources/js/helpers/tracker.js index bc18847..2bc477b 100644 --- a/resources/js/helpers/tracker.js +++ b/resources/js/helpers/tracker.js @@ -1765,11 +1765,15 @@ const collectUnderworld = (state, data) => { }); }; -export const computeState = (data, prizeMap) => { +export const computeState = (config, data, prizeMap) => { const state = {}; collectInventory(state, data.slice(SRAM_ADDR.INV_START), prizeMap); collectOverworld(state, data); collectUnderworld(state, data.slice(SRAM_ADDR.ROOM_DATA_START)); + const amounts = getDungeonAmounts(config, state); + DUNGEONS.forEach(dungeon => { + state[`${dungeon.id}-checks`] = amounts[dungeon.id]; + }); return state; }; @@ -1804,12 +1808,54 @@ const getDungeonAmounts = (config, state) => { return amounts; }; -export const mergeStates = (config, cur, inc) => { - const next = { ...cur, ...inc }; - const amounts = getDungeonAmounts(config, inc); +export const mergeStates = (autoState, manualState) => { + const next = { ...autoState }; + BOOLEAN_STATES.forEach(name => { + if (manualState[name]) { + next[name] = true; + } + }); + INTEGER_STATES.forEach(name => { + next[name] = Math.max(autoState[name] || 0, manualState[name] || 0); + }); DUNGEONS.forEach(dungeon => { - next[`${dungeon.id}-checks`] = amounts[dungeon.id]; + next[`${dungeon.id}-small-key`] += manualState[`${dungeon.id}-small-key`] || 0; + next[`${dungeon.id}-checks`] += manualState[`${dungeon.id}-checks`] || 0; + if (manualState[`${dungeon.id}-big-key`]) { + next[`${dungeon.id}-big-key`] = true; + } + if (manualState[`${dungeon.id}-compass`]) { + next[`${dungeon.id}-compass`] = true; + } + if (manualState[`${dungeon.id}-map`]) { + next[`${dungeon.id}-map`] = true; + } + if (manualState[`${dungeon.id}-boss-defeated`]) { + next[`${dungeon.id}-boss-defeated`] = true; + } + if (manualState[`${dungeon.id}-prize`] && + manualState[`${dungeon.id}-prize`] !== 'crystal' + ) { + next[`${dungeon.id}-prize`] = manualState[`${dungeon.id}-prize`]; + } else if (!next[`${dungeon.id}-prize`]) { + next[`${dungeon.id}-prize`] = 'crystal'; + } + if (manualState[`${dungeon.id}-prize-acquired`]) { + next[`${dungeon.id}-prize-acquired`] = true; + } + }); + OVERWORLD_LOCATIONS.forEach(loc => { + if (manualState[loc.id]) { + next[loc.id] = true; + } + }); + UNDERWORLD_LOCATIONS.forEach(loc => { + if (manualState[loc.id]) { + next[loc.id] = true; + } }); + next['mm-medallion'] = manualState['mm-medallion']; + next['tr-medallion'] = manualState['tr-medallion']; //console.log(next); return next; }; diff --git a/resources/js/hooks/tracker.js b/resources/js/hooks/tracker.js index be5a52f..249a34b 100644 --- a/resources/js/hooks/tracker.js +++ b/resources/js/hooks/tracker.js @@ -1,7 +1,7 @@ import PropTypes from 'prop-types'; import React from 'react'; -import { CONFIG, DUNGEONS, makeEmptyState } from '../helpers/tracker'; +import { CONFIG, DUNGEONS, makeEmptyState, mergeStates } from '../helpers/tracker'; const context = React.createContext({}); @@ -10,6 +10,8 @@ export const useTracker = () => React.useContext(context); export const TrackerProvider = ({ children }) => { const [config, setConfig] = React.useState(CONFIG); const [state, setState] = React.useState(makeEmptyState()); + const [autoState, setAutoState] = React.useState(makeEmptyState()); + const [manualState, setManualState] = React.useState(makeEmptyState()); const [dungeons, setDungeons] = React.useState(DUNGEONS); React.useEffect(() => { @@ -35,8 +37,12 @@ export const TrackerProvider = ({ children }) => { setDungeons(newDungeons); }, [config]); + React.useEffect(() => { + setState(mergeStates(autoState, manualState)); + }, [autoState, manualState]); + const value = React.useMemo(() => { - return { config, setConfig, dungeons, setState, state }; + return { config, setConfig, dungeons, setAutoState, setManualState, state }; }, [config, dungeons, state]); return diff --git a/resources/sass/tracker.scss b/resources/sass/tracker.scss index 5bc5a46..eae60c3 100644 --- a/resources/sass/tracker.scss +++ b/resources/sass/tracker.scss @@ -1,4 +1,9 @@ .tracker { + .auto-tracking { + .custom-toggle { + vertical-align: middle; + } + } .count-display, .med-display { background: black; @@ -39,6 +44,9 @@ } } } + .dungeons { + padding: 1ex; + } .dungeon-ep, .dungeon-pd { margin-top: 1ex; @@ -49,6 +57,9 @@ gap: 1ex; padding: 1ex; } + .inventory { + font-size: 110%; + } .items { display: grid; grid-template-columns: 3em 3em 3em 3em 3em; -- 2.39.2