human bug fix

This commit is contained in:
2025-07-22 10:19:49 +05:30
parent ccf64e0f97
commit 88361b1623
9 changed files with 104 additions and 112 deletions

View File

@@ -6,16 +6,21 @@ import { useProductContext } from '../../products/productContext';
export function useHumanEventManager() {
const { humanStore, productStore, assetStore } = useSceneContext();
const { getHumanById, clearLoadCount, setCurrentPhase } = humanStore();
const { getHumanById, setCurrentPhase } = humanStore();
const { getAssetById } = assetStore();
const { getActionByUuid } = productStore();
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const callbacksRef = useRef<Map<string, (() => void)[]>>(new Map());
const actionQueueRef = useRef<Map<string, { actionType: "worker" | "assembly", actionUuid: string }[]>>(new Map());
const isCooldownRef = useRef<Map<string, boolean>>(new Map());
const isMonitoringRef = useRef(false);
const stateRef = useRef({
humanStates: new Map<string, {
callbacks: (() => void)[],
actionQueue: { actionType: "worker" | "assembly", actionUuid: string, actionName: string }[],
isCooldown: boolean
}>(),
callbackCounts: new Map<string, Map<string, number>>(),
isMonitoring: false
});
const { isPlaying } = usePlayButtonStore();
const { isPaused } = usePauseButtonStore();
@@ -23,10 +28,9 @@ export function useHumanEventManager() {
useEffect(() => {
if (isReset) {
callbacksRef.current.clear();
actionQueueRef.current.clear();
isCooldownRef.current.clear();
isMonitoringRef.current = false;
stateRef.current.humanStates.clear();
stateRef.current.callbackCounts.clear();
stateRef.current.isMonitoring = false;
}
}, [isReset]);
@@ -38,34 +42,64 @@ export function useHumanEventManager() {
const actionType = action.actionType;
if (actionType !== "worker" && actionType !== "assembly") return;
if (!callbacksRef.current.has(humanId)) {
callbacksRef.current.set(humanId, []);
actionQueueRef.current.set(humanId, []);
if (!stateRef.current.callbackCounts.has(humanId)) {
stateRef.current.callbackCounts.set(humanId, new Map());
}
callbacksRef.current.get(humanId)!.push(callback);
actionQueueRef.current.get(humanId)!.push({ actionType, actionUuid });
const actionCounts = stateRef.current.callbackCounts.get(humanId)!;
if (!actionCounts.has(actionUuid)) {
actionCounts.set(actionUuid, 0);
}
isMonitoringRef.current = true;
const currentCount = actionCounts.get(actionUuid)!;
if (actionType === 'worker' && currentCount >= action.loadCount) {
return;
}
if (!stateRef.current.humanStates.has(humanId)) {
stateRef.current.humanStates.set(humanId, {
callbacks: [],
actionQueue: [],
isCooldown: false
});
}
const humanState = stateRef.current.humanStates.get(humanId)!;
humanState.callbacks.push(callback);
humanState.actionQueue.push({ actionType, actionUuid, actionName: action.actionName });
stateRef.current.isMonitoring = true;
};
const removeHumanFromMonitor = (humanId: string) => {
callbacksRef.current.delete(humanId);
actionQueueRef.current.delete(humanId);
isCooldownRef.current.delete(humanId);
// stateRef.current.humanStates.delete(humanId);
if (callbacksRef.current.size === 0) {
isMonitoringRef.current = false;
if (stateRef.current.humanStates.size === 0) {
stateRef.current.isMonitoring = false;
}
};
const getCallbackCount = (humanId: string, actionUuid: string) => {
if (!stateRef.current.callbackCounts.has(humanId)) return 0;
return stateRef.current.callbackCounts.get(humanId)!.get(actionUuid) || 0;
};
const incrementCallbackCount = (humanId: string, actionUuid: string) => {
if (!stateRef.current.callbackCounts.has(humanId)) {
stateRef.current.callbackCounts.set(humanId, new Map());
}
const actionCounts = stateRef.current.callbackCounts.get(humanId)!;
const currentCount = actionCounts.get(actionUuid) || 0;
actionCounts.set(actionUuid, currentCount + 1);
};
useFrame(() => {
if (!isMonitoringRef.current || !isPlaying || isPaused) return;
if (!stateRef.current.isMonitoring || !isPlaying || isPaused) return;
callbacksRef.current.forEach((queue, humanId) => {
if (queue.length === 0 || isCooldownRef.current.get(humanId)) return;
stateRef.current.humanStates.forEach((humanState, humanId) => {
if (humanState.callbacks.length === 0 || humanState.isCooldown) return;
const actionQueue = actionQueueRef.current.get(humanId);
const actionQueue = humanState.actionQueue;
if (!actionQueue || actionQueue.length === 0) return;
const { actionType: expectedActionType, actionUuid } = actionQueue[0];
@@ -75,11 +109,22 @@ export function useHumanEventManager() {
if (!humanAsset || !human || !action || action.actionType !== expectedActionType) return;
let conditionMet = false;
const currentCount = getCallbackCount(humanId, actionUuid);
const currentAction = getActionByUuid(selectedProduct.productUuid, human.currentAction?.actionUuid || '') as HumanAction | undefined;
let conditionMet = false;
if (expectedActionType === "worker") {
if (currentAction && currentAction.actionType === 'worker' && currentCount >= currentAction.loadCount) {
humanState.callbacks.shift();
actionQueue.shift();
if (humanState.callbacks.length === 0) {
removeHumanFromMonitor(humanId);
}
return;
}
if (currentAction && currentAction.actionType === 'worker') {
conditionMet = (
!human.isActive &&
@@ -88,15 +133,6 @@ export function useHumanEventManager() {
human.currentLoad < currentAction.loadCapacity
);
if (human.totalLoadCount >= currentAction.loadCount && actionUuid === human.currentAction?.actionUuid) {
queue.shift();
actionQueue.shift();
if (queue.length === 0) {
removeHumanFromMonitor(humanId);
}
return;
}
if (conditionMet && actionUuid !== human.currentAction?.actionUuid) {
setCurrentPhase(human.modelUuid, 'init');
}
@@ -104,8 +140,7 @@ export function useHumanEventManager() {
conditionMet = (
!human.isActive &&
human.state === "idle" &&
humanAsset.animationState?.current === 'idle' &&
human.currentLoad < action.loadCapacity
humanAsset.animationState?.current === 'idle'
);
if (conditionMet && actionUuid !== human.currentAction?.actionUuid) {
setCurrentPhase(human.modelUuid, 'init');
@@ -127,44 +162,34 @@ export function useHumanEventManager() {
conditionMet = (
!human.isActive &&
human.state === "idle" &&
humanAsset.animationState?.current === 'idle' &&
human.currentLoad < action.loadCapacity
humanAsset.animationState?.current === 'idle'
)
}
if (conditionMet) {
clearLoadCount(human.modelUuid);
}
}
if (conditionMet) {
const callback = queue.shift();
const callback = humanState.callbacks.shift();
actionQueue.shift();
if (callback) callback();
if (callback) {
callback();
incrementCallbackCount(humanId, actionUuid);
}
if (queue.length === 0) {
if (humanState.callbacks.length === 0) {
removeHumanFromMonitor(humanId);
} else {
isCooldownRef.current.set(humanId, true);
humanState.isCooldown = true;
setTimeout(() => {
isCooldownRef.current.set(humanId, false);
humanState.isCooldown = false;
}, 1000);
}
}
});
}, 0);
useEffect(() => {
return () => {
callbacksRef.current.clear();
actionQueueRef.current.clear();
isCooldownRef.current.clear();
isMonitoringRef.current = false;
};
}, []);
});
return {
addHumanToMonitor,
removeHumanFromMonitor,
};
}
}