Add basic hex functionality and clean up hooks and Vector2 class
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import { useEffect, useState, useRef, useCallback } from "react";
|
||||
|
||||
import useDebounce from "./useDebounce";
|
||||
import { diff, applyChanges } from "../helpers/diff";
|
||||
|
||||
/**
|
||||
* @callback setNetworkedState
|
||||
* @param {any} update The updated state or a state function passed into setState
|
||||
* @param {boolean} sync Whether to sync the update with the session
|
||||
* @param {boolean} force Whether to force a full update, usefull when partialUpdates is enabled
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper to sync a react state to a `Session`
|
||||
*
|
||||
* @param {any} initialState
|
||||
* @param {Session} session `Session` instance
|
||||
* @param {string} eventName Name of the event to send to the session
|
||||
* @param {number} debounceRate Amount to debounce before sending to the session (ms)
|
||||
* @param {boolean} partialUpdates Allow sending of partial updates to the session
|
||||
* @param {string} partialUpdatesKey Key to lookup in the state to identify a partial update
|
||||
*
|
||||
* @returns {[any, setNetworkedState]}
|
||||
*/
|
||||
function useNetworkedState(
|
||||
initialState,
|
||||
session,
|
||||
eventName,
|
||||
debounceRate = 500,
|
||||
partialUpdates = true,
|
||||
partialUpdatesKey = "id"
|
||||
) {
|
||||
const [state, _setState] = useState(initialState);
|
||||
// Used to control whether the state needs to be sent to the socket
|
||||
const dirtyRef = useRef(false);
|
||||
|
||||
// Used to force a full update
|
||||
const forceUpdateRef = useRef(false);
|
||||
|
||||
// Update dirty at the same time as state
|
||||
const setState = useCallback((update, sync = true, force = false) => {
|
||||
dirtyRef.current = sync;
|
||||
forceUpdateRef.current = force;
|
||||
_setState(update);
|
||||
}, []);
|
||||
|
||||
const eventNameRef = useRef(eventName);
|
||||
useEffect(() => {
|
||||
eventNameRef.current = eventName;
|
||||
}, [eventName]);
|
||||
|
||||
const debouncedState = useDebounce(state, debounceRate);
|
||||
const lastSyncedStateRef = useRef();
|
||||
useEffect(() => {
|
||||
if (session.socket && dirtyRef.current) {
|
||||
// If partial updates enabled, send just the changes to the socket
|
||||
if (
|
||||
lastSyncedStateRef.current &&
|
||||
debouncedState &&
|
||||
partialUpdates &&
|
||||
!forceUpdateRef.current
|
||||
) {
|
||||
const changes = diff(lastSyncedStateRef.current, debouncedState);
|
||||
if (changes) {
|
||||
const update = { id: debouncedState[partialUpdatesKey], changes };
|
||||
session.socket.emit(`${eventName}_update`, update);
|
||||
}
|
||||
} else {
|
||||
session.socket.emit(eventName, debouncedState);
|
||||
}
|
||||
dirtyRef.current = false;
|
||||
forceUpdateRef.current = false;
|
||||
lastSyncedStateRef.current = debouncedState;
|
||||
}
|
||||
}, [
|
||||
session.socket,
|
||||
eventName,
|
||||
debouncedState,
|
||||
partialUpdates,
|
||||
partialUpdatesKey,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
function handleSocketEvent(data) {
|
||||
_setState(data);
|
||||
lastSyncedStateRef.current = data;
|
||||
}
|
||||
|
||||
function handleSocketUpdateEvent(update) {
|
||||
_setState((prevState) => {
|
||||
if (prevState && prevState[partialUpdatesKey] === update.id) {
|
||||
let newState = { ...prevState };
|
||||
applyChanges(newState, update.changes);
|
||||
if (lastSyncedStateRef.current) {
|
||||
applyChanges(lastSyncedStateRef.current, update.changes);
|
||||
}
|
||||
return newState;
|
||||
} else {
|
||||
return prevState;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
session.socket?.on(eventName, handleSocketEvent);
|
||||
session.socket?.on(`${eventName}_update`, handleSocketUpdateEvent);
|
||||
return () => {
|
||||
session.socket?.off(eventName, handleSocketEvent);
|
||||
session.socket?.off(`${eventName}_update`, handleSocketUpdateEvent);
|
||||
};
|
||||
}, [session.socket, eventName, partialUpdatesKey]);
|
||||
|
||||
return [state, setState];
|
||||
}
|
||||
|
||||
export default useNetworkedState;
|
||||
Reference in New Issue
Block a user