Commit 4ad6b82a authored by timel's avatar timel

feat: remove all unused dependencies

parent 9bbb4813
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
"@react-spring/shared": "^9.7.2", "@react-spring/shared": "^9.7.2",
"@react-spring/types": "^9.7.2", "@react-spring/types": "^9.7.2",
"@react-spring/web": "^9.7.2", "@react-spring/web": "^9.7.2",
"@reduxjs/toolkit": "^1.9.3",
"@testing-library/jest-dom": "^5.16.5", "@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
...@@ -22,7 +21,6 @@ ...@@ -22,7 +21,6 @@
"@types/node": "^16.18.23", "@types/node": "^16.18.23",
"@types/react": "^18.0.33", "@types/react": "^18.0.33",
"@types/react-dom": "^18.0.11", "@types/react-dom": "^18.0.11",
"@types/react-redux": "^7.1.25",
"@types/sql.js": "^1.4.4", "@types/sql.js": "^1.4.4",
"antd": "^5.4.0", "antd": "^5.4.0",
"axios": "^0.27.2", "axios": "^0.27.2",
...@@ -32,7 +30,6 @@ ...@@ -32,7 +30,6 @@
"react-babylonjs": "^3.1.15", "react-babylonjs": "^3.1.15",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-draggable": "^4.4.5", "react-draggable": "^4.4.5",
"react-redux": "^8.0.5",
"react-router-dom": "^6.10.0", "react-router-dom": "^6.10.0",
"react-scripts": "^2.1.3", "react-scripts": "^2.1.3",
"socket.io-client": "^4.6.1", "socket.io-client": "^4.6.1",
...@@ -3180,29 +3177,6 @@ ...@@ -3180,29 +3177,6 @@
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
} }
}, },
"node_modules/@reduxjs/toolkit": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.3.tgz",
"integrity": "sha512-GU2TNBQVofL09VGmuSioNPQIu6Ml0YLf4EJhgj0AvBadRlCGzUWet8372LjvO4fqKZF2vH1xU0htAa7BrK9pZg==",
"dependencies": {
"immer": "^9.0.16",
"redux": "^4.2.0",
"redux-thunk": "^2.4.2",
"reselect": "^4.1.7"
},
"peerDependencies": {
"react": "^16.9.0 || ^17.0.0 || ^18",
"react-redux": "^7.2.1 || ^8.0.2"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-redux": {
"optional": true
}
}
},
"node_modules/@remix-run/router": { "node_modules/@remix-run/router": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.5.0.tgz", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.5.0.tgz",
...@@ -3628,15 +3602,6 @@ ...@@ -3628,15 +3602,6 @@
"integrity": "sha512-pYVNNJ+winC4aek+lZp93sIKxnXt5qMkuKmaqS3WGuTq0Bw1ZDYNBgzG5kkdtwcv+GmYJGo3yEg6z2cKKAiEdw==", "integrity": "sha512-pYVNNJ+winC4aek+lZp93sIKxnXt5qMkuKmaqS3WGuTq0Bw1ZDYNBgzG5kkdtwcv+GmYJGo3yEg6z2cKKAiEdw==",
"dev": true "dev": true
}, },
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"dependencies": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"node_modules/@types/jest": { "node_modules/@types/jest": {
"version": "27.5.2", "version": "27.5.2",
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz",
...@@ -3711,17 +3676,6 @@ ...@@ -3711,17 +3676,6 @@
"@types/react": "*" "@types/react": "*"
} }
}, },
"node_modules/@types/react-redux": {
"version": "7.1.25",
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz",
"integrity": "sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==",
"dependencies": {
"@types/hoist-non-react-statics": "^3.3.0",
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0",
"redux": "^4.0.0"
}
},
"node_modules/@types/scheduler": { "node_modules/@types/scheduler": {
"version": "0.16.2", "version": "0.16.2",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
...@@ -3755,11 +3709,6 @@ ...@@ -3755,11 +3709,6 @@
"@types/jest": "*" "@types/jest": "*"
} }
}, },
"node_modules/@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.57.1", "version": "5.57.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.1.tgz",
...@@ -11005,14 +10954,6 @@ ...@@ -11005,14 +10954,6 @@
"node": ">=4.0.0" "node": ">=4.0.0"
} }
}, },
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/home-or-tmp": { "node_modules/home-or-tmp": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
...@@ -11568,15 +11509,6 @@ ...@@ -11568,15 +11509,6 @@
"node": ">= 4" "node": ">= 4"
} }
}, },
"node_modules/immer": {
"version": "9.0.21",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
"integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
}
},
"node_modules/immutable": { "node_modules/immutable": {
"version": "4.2.4", "version": "4.2.4",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.4.tgz", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.4.tgz",
...@@ -21412,49 +21344,6 @@ ...@@ -21412,49 +21344,6 @@
"loose-envify": "^1.1.0" "loose-envify": "^1.1.0"
} }
}, },
"node_modules/react-redux": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz",
"integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
},
"peerDependencies": {
"@types/react": "^16.8 || ^17.0 || ^18.0",
"@types/react-dom": "^16.8 || ^17.0 || ^18.0",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0",
"react-native": ">=0.59",
"redux": "^4"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
},
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
},
"redux": {
"optional": true
}
}
},
"node_modules/react-redux/node_modules/react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/react-refresh": { "node_modules/react-refresh": {
"version": "0.14.0", "version": "0.14.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
...@@ -23068,22 +22957,6 @@ ...@@ -23068,22 +22957,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/redux": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz",
"integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==",
"dependencies": {
"@babel/runtime": "^7.9.2"
}
},
"node_modules/redux-thunk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
"peerDependencies": {
"redux": "^4"
}
},
"node_modules/regenerate": { "node_modules/regenerate": {
"version": "1.4.2", "version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
...@@ -23453,11 +23326,6 @@ ...@@ -23453,11 +23326,6 @@
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
}, },
"node_modules/reselect": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz",
"integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A=="
},
"node_modules/resize-observer-polyfill": { "node_modules/resize-observer-polyfill": {
"version": "1.5.1", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
...@@ -30955,17 +30823,6 @@ ...@@ -30955,17 +30823,6 @@
"@react-spring/types": "~9.7.2" "@react-spring/types": "~9.7.2"
} }
}, },
"@reduxjs/toolkit": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.3.tgz",
"integrity": "sha512-GU2TNBQVofL09VGmuSioNPQIu6Ml0YLf4EJhgj0AvBadRlCGzUWet8372LjvO4fqKZF2vH1xU0htAa7BrK9pZg==",
"requires": {
"immer": "^9.0.16",
"redux": "^4.2.0",
"redux-thunk": "^2.4.2",
"reselect": "^4.1.7"
}
},
"@remix-run/router": { "@remix-run/router": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.5.0.tgz", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.5.0.tgz",
...@@ -31234,15 +31091,6 @@ ...@@ -31234,15 +31091,6 @@
"integrity": "sha512-pYVNNJ+winC4aek+lZp93sIKxnXt5qMkuKmaqS3WGuTq0Bw1ZDYNBgzG5kkdtwcv+GmYJGo3yEg6z2cKKAiEdw==", "integrity": "sha512-pYVNNJ+winC4aek+lZp93sIKxnXt5qMkuKmaqS3WGuTq0Bw1ZDYNBgzG5kkdtwcv+GmYJGo3yEg6z2cKKAiEdw==",
"dev": true "dev": true
}, },
"@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"requires": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"@types/jest": { "@types/jest": {
"version": "27.5.2", "version": "27.5.2",
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz",
...@@ -31317,17 +31165,6 @@ ...@@ -31317,17 +31165,6 @@
"@types/react": "*" "@types/react": "*"
} }
}, },
"@types/react-redux": {
"version": "7.1.25",
"resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz",
"integrity": "sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==",
"requires": {
"@types/hoist-non-react-statics": "^3.3.0",
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0",
"redux": "^4.0.0"
}
},
"@types/scheduler": { "@types/scheduler": {
"version": "0.16.2", "version": "0.16.2",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
...@@ -31361,11 +31198,6 @@ ...@@ -31361,11 +31198,6 @@
"@types/jest": "*" "@types/jest": "*"
} }
}, },
"@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"@typescript-eslint/eslint-plugin": { "@typescript-eslint/eslint-plugin": {
"version": "5.57.1", "version": "5.57.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.1.tgz",
...@@ -37046,14 +36878,6 @@ ...@@ -37046,14 +36878,6 @@
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
}, },
"hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"requires": {
"react-is": "^16.7.0"
}
},
"home-or-tmp": { "home-or-tmp": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
...@@ -37487,11 +37311,6 @@ ...@@ -37487,11 +37311,6 @@
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ=="
}, },
"immer": {
"version": "9.0.21",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
"integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA=="
},
"immutable": { "immutable": {
"version": "4.2.4", "version": "4.2.4",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.4.tgz", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.4.tgz",
...@@ -45103,26 +44922,6 @@ ...@@ -45103,26 +44922,6 @@
} }
} }
}, },
"react-redux": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz",
"integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==",
"requires": {
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
},
"dependencies": {
"react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
}
}
},
"react-refresh": { "react-refresh": {
"version": "0.14.0", "version": "0.14.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
...@@ -46362,20 +46161,6 @@ ...@@ -46362,20 +46161,6 @@
"strip-indent": "^3.0.0" "strip-indent": "^3.0.0"
} }
}, },
"redux": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz",
"integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==",
"requires": {
"@babel/runtime": "^7.9.2"
}
},
"redux-thunk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
"requires": {}
},
"regenerate": { "regenerate": {
"version": "1.4.2", "version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
...@@ -46662,11 +46447,6 @@ ...@@ -46662,11 +46447,6 @@
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
}, },
"reselect": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz",
"integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A=="
},
"resize-observer-polyfill": { "resize-observer-polyfill": {
"version": "1.5.1", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
export * from "./useApp";
export * from "./useEnv"; export * from "./useEnv";
export * from "./useMeshClick"; export * from "./useMeshClick";
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import type { AppDispatch, RootState } from "@/store";
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
...@@ -23,10 +23,8 @@ import { ConfigProvider, theme } from "antd"; ...@@ -23,10 +23,8 @@ import { ConfigProvider, theme } from "antd";
import zhCN from "antd/locale/zh_CN"; import zhCN from "antd/locale/zh_CN";
import React from "react"; import React from "react";
import ReactDOM from "react-dom/client"; import ReactDOM from "react-dom/client";
import { Provider } from "react-redux";
import { BrowserRouter } from "react-router-dom"; import { BrowserRouter } from "react-router-dom";
import { store } from "./store";
import Neos from "./ui/Neos"; import Neos from "./ui/Neos";
const root = ReactDOM.createRoot( const root = ReactDOM.createRoot(
...@@ -35,14 +33,9 @@ const root = ReactDOM.createRoot( ...@@ -35,14 +33,9 @@ const root = ReactDOM.createRoot(
root.render( root.render(
<React.StrictMode> <React.StrictMode>
<BrowserRouter> <BrowserRouter>
<Provider store={store}> <ConfigProvider theme={{ algorithm: theme.darkAlgorithm }} locale={zhCN}>
<ConfigProvider
theme={{ algorithm: theme.darkAlgorithm }}
locale={zhCN}
>
<Neos /> <Neos />
</ConfigProvider> </ConfigProvider>
</Provider>
</BrowserRouter> </BrowserRouter>
</React.StrictMode> </React.StrictMode>
); );
/*
* Chat状态更新逻辑
*
* */
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { RootState } from "@/store";
export interface chatState {
message: string;
}
const initialState: chatState = {
message: "",
};
const chatSlice = createSlice({
name: "chat",
initialState,
reducers: {
postChat: (state, action: PayloadAction<string>) => {
state.message = action.payload;
},
},
});
export const { postChat } = chatSlice.actions;
export const selectChat = (state: RootState) => state.chat.message;
export default chatSlice.reducer;
import {
ActionReducerMapBuilder,
CaseReducer,
PayloadAction,
} from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { RootState } from "@/store";
import {
createAsyncMetaThunk,
DuelFieldState,
DuelReducer,
extendIdleInteractivities,
extendMeta,
extendState,
Interactivity,
removeCard,
} from "./generic";
import { DuelState } from "./mod";
import { judgeSelf } from "./util";
export interface BanishedZoneState extends DuelFieldState {}
// 初始化除外区状态
export const initBanishedZoneImpl: CaseReducer<
DuelState,
PayloadAction<number>
> = (state, action) => {
const player = action.payload;
if (judgeSelf(player, state)) {
state.meBanishedZone = { inner: [] };
} else {
state.opBanishedZone = { inner: [] };
}
};
// 增加除外区
export const fetchBanishedZoneMeta = createAsyncMetaThunk(
"duel/fetchBanishedZoneMeta"
);
export const banishedZoneCase = (
builder: ActionReducerMapBuilder<DuelState>
) => {
builder.addCase(fetchBanishedZoneMeta.pending, (state, action) => {
// Meta结果没返回之前先更新`ID`
const controler = action.meta.arg.controler;
const sequence = action.meta.arg.sequence;
const code = action.meta.arg.code;
const newExclusion = {
occupant: { id: code, data: {}, text: {} },
location: {
controler,
location: ygopro.CardZone.REMOVED,
},
idleInteractivities: [],
counters: {},
};
if (judgeSelf(controler, state)) {
extendState(state.meBanishedZone, newExclusion, sequence);
} else {
extendState(state.opBanishedZone, newExclusion, sequence);
}
});
builder.addCase(fetchBanishedZoneMeta.fulfilled, (state, action) => {
const controler = action.payload.controler;
const sequence = action.payload.sequence;
const meta = action.payload.meta;
if (judgeSelf(controler, state)) {
extendMeta(state.meBanishedZone, meta, sequence);
} else {
extendMeta(state.opBanishedZone, meta, sequence);
}
});
};
// 删除除外区
export const removeBanishedZoneImpl: CaseReducer<
DuelState,
PayloadAction<{ controler: number; sequence: number }>
> = (state, action) => {
const banishedZone = judgeSelf(action.payload.controler, state)
? state.meBanishedZone
: state.opBanishedZone;
removeCard(banishedZone, action.payload.sequence);
};
export const addBanishedZoneIdleInteractivitiesImpl: DuelReducer<{
player: number;
sequence: number;
interactivity: Interactivity<number>;
}> = (state, action) => {
const banishedZone = judgeSelf(action.payload.player, state)
? state.meBanishedZone
: state.opBanishedZone;
extendIdleInteractivities(
banishedZone,
action.payload.sequence,
action.payload.interactivity
);
};
export const selectMeBanishedZone = (state: RootState) =>
state.duel.meBanishedZone || { inner: [] };
export const selectOpBanishedZone = (state: RootState) =>
state.duel.opBanishedZone || { inner: [] };
import { ygopro } from "@/api";
import {
clearIdleInteractivities,
clearPlaceInteractivities,
DuelReducer,
reloadFieldMeta,
updateCardData,
} from "./generic";
import { judgeSelf } from "./util";
import MsgReloadField = ygopro.StocGameMessage.MsgReloadField;
type MsgUpdateData = ReturnType<
typeof ygopro.StocGameMessage.MsgUpdateData.prototype.toObject
>;
export const clearAllIdleInteractivitiesImpl: DuelReducer<number> = (
state,
action
) => {
const player = action.payload;
const states = judgeSelf(player, state)
? [
state.meHands,
state.meMonsters,
state.meMagics,
state.meGraveyard,
state.meBanishedZone,
state.meExtraDeck,
]
: [
state.opHands,
state.opMonsters,
state.opMagics,
state.opGraveyard,
state.opBanishedZone,
state.opExtraDeck,
];
states.forEach((item) => clearIdleInteractivities(item));
};
export const clearAllPlaceInteractivitiesImpl: DuelReducer<number> = (
state,
action
) => {
const player = action.payload;
const states = judgeSelf(player, state)
? [
state.meHands,
state.meMonsters,
state.meMagics,
state.meGraveyard,
state.meBanishedZone,
]
: [
state.opHands,
state.opMonsters,
state.opMagics,
state.opGraveyard,
state.opBanishedZone,
];
states.forEach((item) => clearPlaceInteractivities(item));
};
export const updateFieldDataImpl: DuelReducer<MsgUpdateData> = (
state,
action
) => {
const player = action.payload.player;
const zone = action.payload.zone;
const actions = action.payload.actions;
if (player !== undefined && zone !== undefined && actions !== undefined) {
switch (zone) {
case ygopro.CardZone.HAND: {
const hand = judgeSelf(player, state) ? state.meHands : state.opHands;
updateCardData(hand, actions);
break;
}
case ygopro.CardZone.EXTRA: {
const extra = judgeSelf(player, state)
? state.meExtraDeck
: state.opExtraDeck;
updateCardData(extra, actions);
break;
}
case ygopro.CardZone.MZONE: {
const monster = judgeSelf(player, state)
? state.meMonsters
: state.opMonsters;
updateCardData(monster, actions);
break;
}
case ygopro.CardZone.SZONE: {
const magics = judgeSelf(player, state)
? state.meMagics
: state.opMagics;
updateCardData(magics, actions);
break;
}
case ygopro.CardZone.GRAVE: {
const graveyard = judgeSelf(player, state)
? state.meGraveyard
: state.opGraveyard;
updateCardData(graveyard, actions);
break;
}
case ygopro.CardZone.REMOVED: {
const BanishedZone = judgeSelf(player, state)
? state.meBanishedZone
: state.opBanishedZone;
updateCardData(BanishedZone, actions);
break;
}
default: {
break;
}
}
}
};
export const reloadFieldImpl: DuelReducer<MsgReloadField> = (state, action) => {
const _duel_rule = action.payload.duel_rule;
// 初始化`DuelState`
state.meDeck = { inner: [] };
state.opDeck = { inner: [] };
state.meExtraDeck = { inner: [] };
state.opExtraDeck = { inner: [] };
state.meMonsters = { inner: [] };
state.opMonsters = { inner: [] };
state.meMagics = { inner: [] };
state.opMagics = { inner: [] };
state.meGraveyard = { inner: [] };
state.opGraveyard = { inner: [] };
state.meBanishedZone = { inner: [] };
state.opBanishedZone = { inner: [] };
state.meHands = { inner: [] };
state.opHands = { inner: [] };
for (const reload of action.payload.actions) {
const player = reload.player;
// DECK
const deck = judgeSelf(player, state) ? state.meDeck : state.opDeck;
reloadFieldMeta(
deck,
reload.zone_actions.filter((item) => item.zone == ygopro.CardZone.DECK),
player
);
// EXTRA_DECK
const extraDeck = judgeSelf(player, state)
? state.meExtraDeck
: state.opExtraDeck;
reloadFieldMeta(
extraDeck,
reload.zone_actions.filter((item) => item.zone == ygopro.CardZone.EXTRA),
player
);
// MZONE
const monster = judgeSelf(player, state)
? state.meMonsters
: state.opMonsters;
reloadFieldMeta(
monster,
reload.zone_actions.filter((item) => item.zone == ygopro.CardZone.MZONE),
player
);
// SZONE
const magics = judgeSelf(player, state) ? state.meMagics : state.opMagics;
reloadFieldMeta(
magics,
reload.zone_actions.filter((item) => item.zone == ygopro.CardZone.SZONE),
player
);
// GRAVE
const graveyard = judgeSelf(player, state)
? state.meGraveyard
: state.opGraveyard;
reloadFieldMeta(
graveyard,
reload.zone_actions.filter((item) => item.zone == ygopro.CardZone.GRAVE),
player
);
// REMOVED
const banishedZone = judgeSelf(player, state)
? state.meBanishedZone
: state.opBanishedZone;
reloadFieldMeta(
banishedZone,
reload.zone_actions.filter(
(item) => item.zone == ygopro.CardZone.REMOVED
),
player
);
// HANDS
const hands = judgeSelf(player, state) ? state.meHands : state.opHands;
reloadFieldMeta(
hands,
reload.zone_actions.filter((item) => item.zone == ygopro.CardZone.HAND),
player
);
}
};
import { CaseReducer, PayloadAction } from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { RootState } from "@/store";
import { CardState, DuelFieldState } from "./generic";
import { DuelState } from "./mod";
import { judgeSelf } from "./util";
export interface DeckState extends DuelFieldState {}
// 初始化卡组状态
export const initDeckImpl: CaseReducer<
DuelState,
PayloadAction<{ player: number; deskSize: number }>
> = (state, action) => {
const player = action.payload.player;
const deckSize = action.payload.deskSize;
let deck: CardState[] = new Array(deckSize);
for (let i = 0; i < deckSize; i++) {
deck.push({
occupant: { id: 0, data: {}, text: {} },
location: {
controler: player,
location: ygopro.CardZone.DECK,
},
idleInteractivities: [],
counters: {},
});
}
if (judgeSelf(player, state)) {
state.meDeck = { inner: deck };
} else {
state.opDeck = { inner: deck };
}
};
export const selectMeDeck = (state: RootState) =>
state.duel.meDeck || { inner: [] };
export const selectOpDeck = (state: RootState) =>
state.duel.opDeck || { inner: [] };
import { ActionReducerMapBuilder } from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { RootState } from "@/store";
import {
createAsyncMetaThunk,
createAsyncRepeatedMetaThunk,
DuelFieldState,
DuelReducer,
extendIdleInteractivities,
extendMeta,
extendState,
Interactivity,
removeCard,
updateCardMeta,
} from "./generic";
import { DuelState } from "./mod";
import { judgeSelf } from "./util";
export interface ExtraDeckState extends DuelFieldState {}
// 初始化额外卡组
export const initMeExtraDeckMeta = createAsyncRepeatedMetaThunk(
"duel/initExtraDeckMeta"
);
// 增加额外卡组
export const fetchExtraDeckMeta = createAsyncMetaThunk(
"duel/fetchExtraDeckMeta"
);
export const extraDeckCase = (builder: ActionReducerMapBuilder<DuelState>) => {
builder.addCase(initMeExtraDeckMeta.pending, (state, action) => {
const _ = action.meta.arg.controler;
const ids = action.meta.arg.codes;
const cards = ids.map((id) => {
return {
occupant: { id, data: {}, text: {} },
location: {
location: ygopro.CardZone.EXTRA,
},
idleInteractivities: [],
counters: {},
};
});
state.meExtraDeck = { inner: cards };
});
builder.addCase(initMeExtraDeckMeta.fulfilled, (state, action) => {
const _ = action.payload.controler;
const metas = action.payload.metas;
updateCardMeta(state.meExtraDeck, metas);
});
builder.addCase(fetchExtraDeckMeta.pending, (state, action) => {
const controler = action.meta.arg.controler;
const sequence = action.meta.arg.sequence;
const code = action.meta.arg.code;
const newExtraDeck = {
occupant: { id: code, data: {}, text: {} },
location: {
controler,
location: ygopro.CardZone.EXTRA,
},
idleInteractivities: [],
counters: {},
};
const extraDeck = judgeSelf(controler, state)
? state.meExtraDeck
: state.opExtraDeck;
extendState(extraDeck, newExtraDeck, sequence);
});
builder.addCase(fetchExtraDeckMeta.fulfilled, (state, action) => {
const controler = action.payload.controler;
const sequence = action.payload.sequence;
const meta = action.payload.meta;
const extraDeck = judgeSelf(controler, state)
? state.meExtraDeck
: state.opExtraDeck;
extendMeta(extraDeck, meta, sequence);
});
};
// 删除额外卡组
export const removeExtraDeckImpl: DuelReducer<{
controler: number;
sequence: number;
}> = (state, action) => {
const extraDeck = judgeSelf(action.payload.controler, state)
? state.meExtraDeck
: state.opExtraDeck;
removeCard(extraDeck, action.payload.sequence);
};
export const addExtraDeckIdleInteractivitiesImpl: DuelReducer<{
player: number;
sequence: number;
interactivity: Interactivity<number>;
}> = (state, action) => {
const extraDeck = judgeSelf(action.payload.player, state)
? state.meExtraDeck
: state.opExtraDeck;
extendIdleInteractivities(
extraDeck,
action.payload.sequence,
action.payload.interactivity
);
};
export const selectMeExtraDeck = (state: RootState) =>
state.duel.meExtraDeck || { inner: [] };
export const selectOpExtraDeck = (state: RootState) =>
state.duel.opExtraDeck || { inner: [] };
import {
AsyncThunk,
CaseReducer,
createAsyncThunk,
PayloadAction,
} from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { CardMeta, fetchCard } from "@/api/cards";
import { DuelState } from "./mod";
import ReloadFieldAction = ygopro.StocGameMessage.MsgReloadField.ZoneAction;
type UpdateDataAction = ReturnType<
typeof ygopro.StocGameMessage.MsgUpdateData.Action.prototype.toObject
>;
export type DuelReducer<T> = CaseReducer<DuelState, PayloadAction<T>>;
export interface DuelFieldState {
inner: CardState[];
}
export interface CardState {
occupant?: CardMeta; // 占据此位置的卡牌元信息
location: {
controler?: number;
location?: number;
position?: ygopro.CardPosition;
overlay_sequence?: number;
}; // 位置信息
idleInteractivities: Interactivity<number>[]; // IDLE状态下的互动信息
placeInteractivities?: Interactivity<{
controler: number;
zone: ygopro.CardZone;
sequence: number;
}>; // 选择位置状态下的互动信息
overlay_materials?: CardMeta[]; // 超量素材
counters: { [type: number]: number }; // 指示器
reload?: boolean; // 这个字段会在收到MSG_RELOAD_FIELD的时候设置成true,在收到MSG_UPDATE_DATE的时候设置成false
}
export enum InteractType {
// 可普通召唤
SUMMON = 1,
// 可特殊召唤
SP_SUMMON = 2,
// 可改变表示形式
POS_CHANGE = 3,
// 可前场放置
MSET = 4,
// 可后场放置
SSET = 5,
// 可发动效果
ACTIVATE = 6,
// 可作为位置选择
PLACE_SELECTABLE = 7,
// 可攻击
ATTACK = 8,
}
export interface Interactivity<T> {
interactType: InteractType;
// 如果`interactType`是`ACTIVATE`,这个字段是对应的效果编号
activateIndex?: number;
// 如果`interactType`是`ATTACK`,这个字段表示是否可以直接攻击
directAttackAble?: boolean;
// 用户点击后,需要回传给服务端的`response`
response: T;
}
export function createAsyncMetaThunk(name: string): AsyncThunk<
{ controler: number; sequence: number; meta: CardMeta },
{
controler: number;
sequence: number;
position?: ygopro.CardPosition;
code: number;
},
{}
> {
return createAsyncThunk(
name,
async (param: {
controler: number;
sequence: number;
position?: ygopro.CardPosition;
code: number;
}) => {
const code = param.code;
const meta = await fetchCard(code, true);
const response = {
controler: param.controler,
sequence: param.sequence,
meta,
};
return response;
}
);
}
export function createAsyncRepeatedMetaThunk(
name: string
): AsyncThunk<
{ controler: number; metas: CardMeta[] },
{ controler: number; codes: number[] },
{}
> {
return createAsyncThunk(
name,
async (param: { controler: number; codes: number[] }) => {
const controler = param.controler;
const Ids = param.codes;
const metas = await Promise.all(
Ids.map(async (id) => {
if (id == 0) {
return { id, data: {}, text: {} };
} else {
return await fetchCard(id, true);
}
})
);
const response = { controler, metas };
return response;
}
);
}
/*
* 扩充决斗区域卡片内容
*
* @param state - 需要扩充的区域,比如`MonsterState`
* @param newState - 新增加的`CardState`
* @sequence - 新增加的卡片的序列号,可选,如果为空则补充到列表末尾
*
* */
export function extendState<T extends DuelFieldState>(
state: T | undefined,
newState: CardState,
sequence?: number
) {
if (state) {
let index = sequence !== undefined ? sequence : state.inner.length;
state.inner.splice(index, 0, newState);
}
}
export function extendOccupant<T extends DuelFieldState>(
state: T | undefined,
newMeta: CardMeta,
sequence: number,
position?: ygopro.CardPosition
) {
if (state) {
const target = state.inner.find((_, idx) => idx == sequence);
if (target) {
target.occupant = newMeta;
if (typeof position !== "undefined") {
target.location.position = position;
}
}
}
}
export function extendMeta<T extends DuelFieldState>(
state: T | undefined,
newMeta: CardMeta,
sequence: number
) {
if (state) {
const target = state.inner.find((_, idx) => idx == sequence);
if (target) {
target.occupant = newMeta;
}
}
}
export function extendPlaceInteractivity<T extends DuelFieldState>(
state: T | undefined,
controler: number,
sequence: number,
zone: ygopro.CardZone
) {
if (state) {
const target = state.inner.find((_, idx) => idx == sequence);
if (target) {
target.placeInteractivities = {
interactType: InteractType.PLACE_SELECTABLE,
response: {
controler,
zone,
sequence,
},
};
}
}
}
export function clearPlaceInteractivities<T extends DuelFieldState>(
state: T | undefined
) {
if (state) {
for (let item of state.inner) {
item.placeInteractivities = undefined;
}
}
}
export function removeCard<T extends DuelFieldState>(
state: T | undefined,
sequence: number
) {
if (state) {
state.inner = state.inner.filter((_, idx) => idx != sequence);
}
}
export function removeOccupant<T extends DuelFieldState>(
state: T | undefined,
sequence: number
) {
if (state) {
const target = state.inner.find((_, idx) => idx == sequence);
if (target) {
target.occupant = undefined;
}
}
}
export function removeOverlay<T extends DuelFieldState>(
state: T | undefined,
sequence: number
) {
if (state) {
const target = state.inner.find((_, idx) => idx == sequence);
if (target) {
target.overlay_materials = [];
}
}
}
export function insertCard<T extends DuelFieldState>(
state: T | undefined,
sequence: number,
card: CardState
) {
if (state) {
state.inner.splice(sequence, 0, card);
}
}
export function updateCardMeta<T extends DuelFieldState>(
state: T | undefined,
metas: CardMeta[]
) {
if (state) {
state.inner.forEach((item) => {
metas.forEach((meta) => {
if (item.occupant?.id === meta.id) {
item.occupant = meta;
}
});
});
}
}
export function extendIdleInteractivities<T extends DuelFieldState>(
state: T | undefined,
sequence: number,
interactivity: Interactivity<number>
) {
if (state) {
const target = state.inner.find((_, idx) => idx == sequence);
if (target) {
target.idleInteractivities.push(interactivity);
}
}
}
export function clearIdleInteractivities<T extends DuelFieldState>(
state: T | undefined
) {
if (state) {
state.inner.forEach((item) => {
item.idleInteractivities = [];
});
}
}
export function setPosition<T extends DuelFieldState>(
state: T | undefined,
sequence: number,
position: ygopro.CardPosition
) {
const target = state?.inner.find((_, idx) => idx == sequence);
if (target && target.occupant) {
target.location.position = position;
}
}
export function updateCardData<T extends DuelFieldState>(
state: T | undefined,
actions: UpdateDataAction[]
) {
for (const payload of actions) {
const sequence = payload.location?.sequence;
if (typeof sequence !== "undefined") {
const target = state?.inner.find((_, idx) => idx == sequence);
if (target && (target.occupant || target.reload)) {
if (target.occupant === undefined) {
target.occupant = { id: payload.code!, data: {}, text: {} };
}
const occupant = target.occupant;
// 目前只更新以下字段
if (payload.code !== undefined && payload.code >= 0) {
occupant.id = payload.code;
occupant.text.id = payload.code;
}
if (payload.location !== undefined) {
target.location.position = payload.location.position;
}
if (payload.type_ !== undefined && payload.type_ >= 0) {
occupant.data.type = payload.type_;
}
if (payload.level !== undefined && payload.level >= 0) {
occupant.data.level = payload.level;
}
if (payload.attribute !== undefined && payload.attribute >= 0) {
occupant.data.attribute = payload.attribute;
}
if (payload.race !== undefined && payload.race >= 0) {
occupant.data.race = payload.race;
}
if (payload.attack !== undefined && payload.attack >= 0) {
occupant.data.atk = payload.attack;
}
if (payload.defense !== undefined && payload.defense >= 0) {
occupant.data.def = payload.defense;
}
// TODO: counters
}
if (target?.reload) {
target.reload = false;
}
}
}
}
export function reloadFieldMeta<T extends DuelFieldState>(
state: T,
actions: ReloadFieldAction[],
controler: number
) {
actions.sort((a, b) => a.sequence - b.sequence);
const cards = actions.map((action) => {
// FIXME: OVERLAY
return {
location: {
controler,
location: action.zone,
position: action.position,
},
idleInteractivities: [],
counters: {},
reload: true,
};
});
state.inner = cards;
}
import {
ActionReducerMapBuilder,
CaseReducer,
PayloadAction,
} from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { RootState } from "@/store";
import {
createAsyncMetaThunk,
DuelFieldState,
DuelReducer,
extendIdleInteractivities,
extendMeta,
extendState,
Interactivity,
removeCard,
} from "./generic";
import { DuelState } from "./mod";
import { judgeSelf } from "./util";
export interface GraveyardState extends DuelFieldState {}
// 初始化墓地状态
export const initGraveyardImpl: CaseReducer<
DuelState,
PayloadAction<number>
> = (state, action) => {
const player = action.payload;
if (judgeSelf(player, state)) {
state.meGraveyard = { inner: [] };
} else {
state.opGraveyard = { inner: [] };
}
};
// 增加墓地
export const fetchGraveyardMeta = createAsyncMetaThunk(
"duel/fetchGraveyardMeta"
);
export const graveyardCase = (builder: ActionReducerMapBuilder<DuelState>) => {
builder.addCase(fetchGraveyardMeta.pending, (state, action) => {
// Meta结果没返回之前先更新`ID`
const controler = action.meta.arg.controler;
const sequence = action.meta.arg.sequence;
const code = action.meta.arg.code;
const newGraveyard = {
occupant: { id: code, data: {}, text: {} },
location: {
controler,
location: ygopro.CardZone.GRAVE,
},
idleInteractivities: [],
counters: {},
};
if (judgeSelf(controler, state)) {
extendState(state.meGraveyard, newGraveyard, sequence);
} else {
extendState(state.opGraveyard, newGraveyard, sequence);
}
});
builder.addCase(fetchGraveyardMeta.fulfilled, (state, action) => {
const controler = action.payload.controler;
const sequence = action.payload.sequence;
const meta = action.payload.meta;
if (judgeSelf(controler, state)) {
extendMeta(state.meGraveyard, meta, sequence);
} else {
extendMeta(state.opGraveyard, meta, sequence);
}
});
};
// 删除墓地
export const removeGraveyardImpl: CaseReducer<
DuelState,
PayloadAction<{ controler: number; sequence: number }>
> = (state, action) => {
const graveyard = judgeSelf(action.payload.controler, state)
? state.meGraveyard
: state.opGraveyard;
removeCard(graveyard, action.payload.sequence);
};
export const addGraveyardIdleInteractivitiesImpl: DuelReducer<{
player: number;
sequence: number;
interactivity: Interactivity<number>;
}> = (state, action) => {
const graveyard = judgeSelf(action.payload.player, state)
? state.meGraveyard
: state.opGraveyard;
extendIdleInteractivities(
graveyard,
action.payload.sequence,
action.payload.interactivity
);
};
export const selectMeGraveyard = (state: RootState) =>
state.duel.meGraveyard || { inner: [] };
export const selectOpGraveyard = (state: RootState) =>
state.duel.opGraveyard || { inner: [] };
import {
ActionReducerMapBuilder,
CaseReducer,
PayloadAction,
} from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { RootState } from "@/store";
import {
createAsyncMetaThunk,
createAsyncRepeatedMetaThunk,
DuelFieldState,
extendMeta,
insertCard,
Interactivity,
removeCard,
updateCardMeta,
} from "./generic";
import { DuelState } from "./mod";
import { judgeSelf } from "./util";
export interface HandState extends DuelFieldState {}
// 增加手牌
export const fetchHandsMeta = createAsyncRepeatedMetaThunk(
"duel/fetchHandsMeta"
);
// 清空手牌互动性
export const clearHandsIdleInteractivityImpl: CaseReducer<
DuelState,
PayloadAction<number>
> = (state, action) => {
const player = action.payload;
const hands = judgeSelf(player, state) ? state.meHands : state.opHands;
if (hands) {
for (let hand of hands.inner) {
hand.idleInteractivities = [];
}
}
};
// 添加手牌互动性
export const addHandsIdleInteractivityImpl: CaseReducer<
DuelState,
PayloadAction<{
player: number;
sequence: number;
interactivity: Interactivity<number>;
}>
> = (state, action) => {
const player = action.payload.player;
const hands = judgeSelf(player, state) ? state.meHands : state.opHands;
if (hands) {
const sequence = action.payload.sequence;
const interactivity = action.payload.interactivity;
hands.inner[sequence].idleInteractivities.push(interactivity);
}
};
// 删除手牌
export const removeHandImpl: CaseReducer<
DuelState,
PayloadAction<[number, number]>
> = (state, action) => {
const controler = action.payload[0];
const sequence = action.payload[1];
const hands = judgeSelf(controler, state) ? state.meHands : state.opHands;
removeCard(hands, sequence);
};
// 在特定位置增加手牌
export const insertHandMeta = createAsyncMetaThunk("duel/insertHandMeta");
export const updateHandsMeta = createAsyncRepeatedMetaThunk(
"duel/updateHandsMeta"
);
export const handsCase = (builder: ActionReducerMapBuilder<DuelState>) => {
builder.addCase(fetchHandsMeta.pending, (state, action) => {
// Meta结果没返回之前先更新手牌`ID`
const player = action.meta.arg.controler;
const ids = action.meta.arg.codes;
const cards = ids.map((id) => {
return {
occupant: { id, data: {}, text: {} },
location: {
controler: player,
location: ygopro.CardZone.HAND,
},
counters: {},
idleInteractivities: [],
};
});
if (judgeSelf(player, state)) {
if (state.meHands) {
state.meHands.inner = state.meHands.inner.concat(cards);
} else {
state.meHands = { inner: cards };
}
} else {
if (state.opHands) {
state.opHands.inner = state.opHands.inner.concat(cards);
} else {
state.opHands = { inner: cards };
}
}
});
builder.addCase(fetchHandsMeta.fulfilled, (state, action) => {
// `Meta`结果回来后更新手牌的`Meta`结果
const player = action.payload.controler;
const metas = action.payload.metas;
const hands = judgeSelf(player, state) ? state.meHands : state.opHands;
updateCardMeta(hands, metas);
});
builder.addCase(insertHandMeta.pending, (state, action) => {
const controler = action.meta.arg.controler;
const sequence = action.meta.arg.sequence;
const code = action.meta.arg.code;
const hands = judgeSelf(controler, state) ? state.meHands : state.opHands;
insertCard(hands, sequence, {
occupant: { id: code, data: {}, text: {} },
location: { controler },
idleInteractivities: [],
counters: {},
});
});
builder.addCase(insertHandMeta.fulfilled, (state, action) => {
const controler = action.payload.controler;
const sequence = action.payload.sequence;
const meta = action.payload.meta;
const hands = judgeSelf(controler, state) ? state.meHands : state.opHands;
extendMeta(hands, meta, sequence);
});
builder.addCase(updateHandsMeta.pending, (state, action) => {
const controler = action.meta.arg.controler;
const codes = action.meta.arg.codes;
const metas = codes.map((code) => {
return {
occupant: { id: code, data: {}, text: {} },
location: {
controler,
location: ygopro.CardZone.HAND,
},
idleInteractivities: [],
counters: {},
};
});
const hands = judgeSelf(controler, state) ? state.meHands : state.opHands;
if (hands) {
hands.inner = metas;
}
});
builder.addCase(updateHandsMeta.fulfilled, (state, action) => {
const controler = action.payload.controler;
const metas = action.payload.metas;
const hands = judgeSelf(controler, state) ? state.meHands : state.opHands;
updateCardMeta(hands, metas);
});
};
export const selectMeHands = (state: RootState) =>
state.duel.meHands || { inner: [] };
export const selectOpHands = (state: RootState) =>
state.duel.opHands || { inner: [] };
import { ActionReducerMapBuilder, createAsyncThunk } from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { fetchCard } from "@/api/cards";
import { DESCRIPTION_LIMIT, fetchStrings, getStrings } from "@/api/strings";
import { RootState } from "@/store";
import { DuelReducer } from "./generic";
import { DuelState } from "./mod";
import { findCardByLocation } from "./util";
export interface HintState {
code: number;
msg?: string;
esHint?: string;
esSelectHint?: string;
}
export const initHintImpl: DuelReducer<void> = (state) => {
state.hint = { code: 0 };
};
export const fetchCommonHintMeta = createAsyncThunk(
"duel/fetchCommonHintMeta",
async (hintData: number) => {
return fetchStrings("!system", hintData);
}
);
export const fetchSelectHintMeta = createAsyncThunk(
"duel/fetchSelectHintMeta",
async (param: { selectHintData: number; esHint?: string }) => {
const selectHintData = param.selectHintData;
let selectHintMeta = "";
if (selectHintData > DESCRIPTION_LIMIT) {
// 针对`MSG_SELECT_PLACE`的特化逻辑
const cardMeta = await fetchCard(selectHintData, true);
selectHintMeta = fetchStrings("!system", 569).replace(
"[%ls]",
cardMeta.text.name || "[?]"
);
} else {
selectHintMeta = await getStrings(selectHintData);
}
return {
selectHintMeta,
esHint: param.esHint,
};
}
);
export const fetchEsHintMeta = createAsyncThunk(
"duel/fetchEsHintMeta",
async (param: {
originMsg: string | number;
location?: ygopro.CardLocation;
cardID?: number;
}) => {
const originMsg =
typeof param.originMsg === "string"
? param.originMsg
: fetchStrings("!system", param.originMsg);
const location = param.location;
if (param.cardID) {
const cardMeta = await fetchCard(param.cardID, true);
return { originMsg, cardMeta, location };
} else {
return { originMsg, location };
}
}
);
export const hintCase = (builder: ActionReducerMapBuilder<DuelState>) => {
builder.addCase(fetchCommonHintMeta.pending, (state, action) => {
const code = action.meta.arg;
if (state.hint) {
state.hint.code = code;
}
});
builder.addCase(fetchCommonHintMeta.fulfilled, (state, action) => {
const hintMeta = action.payload;
if (state.hint) {
state.hint.msg = hintMeta;
}
});
builder.addCase(fetchSelectHintMeta.pending, (state, action) => {
const code = action.meta.arg.selectHintData;
if (state.hint) {
state.hint.code = code;
}
});
builder.addCase(fetchSelectHintMeta.fulfilled, (state, action) => {
const selectHintMsg = action.payload.selectHintMeta;
const esHint = action.payload.esHint;
const hint = state.hint;
if (hint) {
if (hint.code > DESCRIPTION_LIMIT) {
// 针对`MSG_SELECT_PLACE`的特化逻辑
hint.msg = selectHintMsg;
} else {
hint.esSelectHint = selectHintMsg;
if (esHint) hint.esHint = esHint;
}
}
});
builder.addCase(fetchEsHintMeta.fulfilled, (state, action) => {
const originMsg = action.payload.originMsg;
const cardMeta = action.payload.cardMeta;
const location = action.payload.location;
const hint = state.hint;
if (hint) {
let esHint = originMsg;
if (cardMeta?.text.name) {
esHint = originMsg.replace("[?]", cardMeta.text.name);
}
if (location) {
const fieldMeta = findCardByLocation(state, location);
if (fieldMeta?.occupant?.text.name) {
esHint = originMsg.replace("[?]", fieldMeta.occupant.text.name);
}
}
hint.esHint = esHint;
}
});
};
export const selectHint = (state: RootState) => state.duel.hint;
import { CaseReducer, PayloadAction } from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { RootState } from "@/store";
import { DuelState } from "./mod";
import { judgeSelf } from "./util";
import MsgUpdateHp = ygopro.StocGameMessage.MsgUpdateHp;
export interface InitInfo {
masterRule?: string;
life: number;
deckSize: number;
extraSize: number;
}
// 更新自己的初始生命值,卡组信息
export const infoInitImpl: CaseReducer<
DuelState,
PayloadAction<[number, InitInfo]>
> = (state, action) => {
const player = action.payload[0];
const initInfo = action.payload[1];
if (judgeSelf(player, state)) {
state.meInitInfo = initInfo;
} else {
state.opInitInfo = initInfo;
}
};
export const updateHpImpl: CaseReducer<
DuelState,
PayloadAction<ygopro.StocGameMessage.MsgUpdateHp>
> = (state, action) => {
const player = action.payload.player;
const actionType = action.payload.type_;
const value = action.payload.value;
const info = judgeSelf(player, state) ? state.meInitInfo : state.opInitInfo;
if (info) {
switch (actionType) {
case MsgUpdateHp.ActionType.DAMAGE: {
info.life = info.life - value;
break;
}
case MsgUpdateHp.ActionType.RECOVER: {
info.life = info.life + value;
break;
}
default: {
break;
}
}
}
};
export const selectMeInitInfo = (state: RootState) => state.duel.meInitInfo;
export const selectOpInitInfo = (state: RootState) => state.duel.opInitInfo;
import {
ActionReducerMapBuilder,
CaseReducer,
PayloadAction,
} from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { RootState } from "@/store";
import {
clearIdleInteractivities,
clearPlaceInteractivities,
createAsyncMetaThunk,
DuelFieldState,
extendIdleInteractivities,
extendOccupant,
extendPlaceInteractivity,
Interactivity,
removeOccupant,
setPosition,
} from "./generic";
import { DuelState } from "./mod";
import { judgeSelf } from "./util";
export interface MagicState extends DuelFieldState {}
// 初始化自己的魔法陷阱区状态
export const initMagicsImpl: CaseReducer<DuelState, PayloadAction<number>> = (
state,
action
) => {
const player = action.payload;
const magics = {
inner: [
{
location: {
controler: player,
location: ygopro.CardZone.SZONE,
},
idleInteractivities: [],
counters: {},
},
{
location: {
controler: player,
location: ygopro.CardZone.SZONE,
},
idleInteractivities: [],
counters: {},
},
{
location: {
controler: player,
location: ygopro.CardZone.SZONE,
},
idleInteractivities: [],
counters: {},
},
{
location: {
controler: player,
location: ygopro.CardZone.SZONE,
},
idleInteractivities: [],
counters: {},
},
{
location: {
controler: player,
location: ygopro.CardZone.SZONE,
},
idleInteractivities: [],
counters: {},
},
{
// 场地区
location: {
controler: player,
location: ygopro.CardZone.SZONE,
},
idleInteractivities: [],
counters: {},
},
],
};
if (judgeSelf(player, state)) {
state.meMagics = magics;
} else {
state.opMagics = magics;
}
};
export const addMagicPlaceInteractivitiesImpl: CaseReducer<
DuelState,
PayloadAction<[number, number]>
> = (state, action) => {
const controler = action.payload[0];
const sequence = action.payload[1];
const magics = judgeSelf(controler, state) ? state.meMagics : state.opMagics;
extendPlaceInteractivity(magics, controler, sequence, ygopro.CardZone.SZONE);
};
export const clearMagicPlaceInteractivitiesImpl: CaseReducer<
DuelState,
PayloadAction<number>
> = (state, action) => {
const player = action.payload;
const magics = judgeSelf(player, state) ? state.meMagics : state.opMagics;
clearPlaceInteractivities(magics);
};
export const addMagicIdleInteractivitiesImpl: CaseReducer<
DuelState,
PayloadAction<{
player: number;
sequence: number;
interactivity: Interactivity<number>;
}>
> = (state, action) => {
const magics = judgeSelf(action.payload.player, state)
? state.meMagics
: state.opMagics;
extendIdleInteractivities(
magics,
action.payload.sequence,
action.payload.interactivity
);
};
export const clearMagicIdleInteractivitiesImpl: CaseReducer<
DuelState,
PayloadAction<number>
> = (state, action) => {
const magics = judgeSelf(action.payload, state)
? state.meMagics
: state.opMagics;
clearIdleInteractivities(magics);
};
// 增加魔法陷阱
export const fetchMagicMeta = createAsyncMetaThunk("duel/fetchMagicMeta");
export const magicCase = (builder: ActionReducerMapBuilder<DuelState>) => {
builder.addCase(fetchMagicMeta.pending, (state, action) => {
// Meta结果没返回之前先更新`ID`
const controler = action.meta.arg.controler;
const sequence = action.meta.arg.sequence;
const position = action.meta.arg.position;
const code = action.meta.arg.code;
const meta = { id: code, data: {}, text: {} };
if (judgeSelf(controler, state)) {
extendOccupant(state.meMagics, meta, sequence, position);
} else {
extendOccupant(state.opMagics, meta, sequence, position);
}
});
builder.addCase(fetchMagicMeta.fulfilled, (state, action) => {
const controler = action.payload.controler;
const sequence = action.payload.sequence;
const meta = action.payload.meta;
if (judgeSelf(controler, state)) {
extendOccupant(state.meMagics, meta, sequence);
} else {
extendOccupant(state.opMagics, meta, sequence);
}
});
};
// 删除魔法陷阱
export const removeMagicImpl: CaseReducer<
DuelState,
PayloadAction<{ controler: number; sequence: number }>
> = (state, action) => {
const controler = action.payload.controler;
const magics = judgeSelf(controler, state) ? state.meMagics : state.opMagics;
removeOccupant(magics, action.payload.sequence);
};
// 改变魔法表示形式
export const setMagicPositionImpl: CaseReducer<
DuelState,
PayloadAction<{
controler: number;
sequence: number;
position: ygopro.CardPosition;
}>
> = (state, action) => {
const controler = action.payload.controler;
const sequence = action.payload.sequence;
const position = action.payload.position;
const magics = judgeSelf(controler, state) ? state.meMagics : state.opMagics;
setPosition(magics, sequence, position);
};
export const selectMeMagics = (state: RootState) =>
state.duel.meMagics || { inner: [] };
export const selectOpMagics = (state: RootState) =>
state.duel.opMagics || { inner: [] };
/*
* 对局内的状态更新逻辑
*
* */
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { RootState } from "@/store";
import {
addBanishedZoneIdleInteractivitiesImpl,
banishedZoneCase,
BanishedZoneState,
initBanishedZoneImpl,
removeBanishedZoneImpl,
} from "./banishedZoneSlice";
import {
clearAllIdleInteractivitiesImpl,
clearAllPlaceInteractivitiesImpl,
reloadFieldImpl,
updateFieldDataImpl,
} from "./commonSlice";
import { DeckState, initDeckImpl } from "./deckSlice";
import {
addExtraDeckIdleInteractivitiesImpl,
extraDeckCase,
ExtraDeckState,
removeExtraDeckImpl,
} from "./extraDeckSlice";
import {
addGraveyardIdleInteractivitiesImpl,
graveyardCase,
GraveyardState,
initGraveyardImpl,
removeGraveyardImpl,
} from "./graveyardSlice";
import {
addHandsIdleInteractivityImpl,
clearHandsIdleInteractivityImpl,
handsCase,
HandState,
removeHandImpl,
} from "./handsSlice";
import { hintCase, HintState, initHintImpl } from "./hintSlice";
import { infoInitImpl, InitInfo, updateHpImpl } from "./initInfoSlice";
import {
addMagicIdleInteractivitiesImpl,
addMagicPlaceInteractivitiesImpl,
clearMagicIdleInteractivitiesImpl,
clearMagicPlaceInteractivitiesImpl,
initMagicsImpl,
magicCase,
MagicState,
removeMagicImpl,
setMagicPositionImpl,
} from "./magicSlice";
import {
checkCardModalCase,
checkCardModalV2Case,
checkCardModalV3Case,
clearCheckCounterImpl,
ModalState,
optionModalCase,
resetCheckCardModalImpl,
resetCheckCardModalV2Impl,
resetCheckCardModalV3Impl,
resetOptionModalImpl,
resetPositionModalImpl,
resetSortCardModalImpl,
setCardListModalInfoImpl,
setCardListModalIsOpenImpl,
setCardModalCountersImpl,
setCardModalInteractiviesImpl,
setCardModalIsOpenImpl,
setCardModalMetaImpl,
setCheckCardMOdalCancelAbleImpl,
setCheckCardModalCancelResponseImpl,
setCheckCardModalIsOpenImpl,
setCheckCardModalMinMaxImpl,
setCheckCardModalOnSubmitImpl,
setCheckCardModalV2CancelAbleImpl,
setCheckCardModalV2FinishAbleImpl,
setCheckCardModalV2IsOpenImpl,
setCheckCardModalV2MinMaxImpl,
setCheckCardModalV2ResponseAbleImpl,
setCheckCardModalV3AllLevelImpl,
setCheckCardModalV3IsOpenImpl,
setCheckCardModalV3MinMaxImpl,
setCheckCardModalV3OverFlowImpl,
setCheckCardModalV3ResponseAbleImpl,
setCheckCounterImpl,
setOptionModalIsOpenImpl,
setPositionModalIsOpenImpl,
setPositionModalPositionsImpl,
setSortCardModalIsOpenImpl,
setYesNoModalIsOpenImpl,
sortCardModalCase,
YesNoModalCase,
} from "./modal/mod";
import {
addMonsterIdleInteractivitiesImpl,
addMonsterPlaceInteractivitiesImpl,
clearMonsterIdleInteractivitiesImpl,
clearMonsterPlaceInteractivitiesImpl,
initMonstersImpl,
monsterCase,
MonsterState,
removeMonsterImpl,
removeOverlayImpl,
setMonsterPositionImpl,
updateMonsterCountersImpl,
} from "./monstersSlice";
import {
newPhaseImpl,
PhaseState,
setEnableBpImpl,
setEnableEpImpl,
setEnableM2Impl,
} from "./phaseSlice";
import { TimeLimit, updateTimeLimitImpl } from "./timeLimit";
import { newTurnImpl } from "./turnSlice";
import MsgWin = ygopro.StocGameMessage.MsgWin;
export interface DuelState {
selfType?: number;
meInitInfo?: InitInfo; // 自己的初始状态
opInitInfo?: InitInfo; // 对手的初始状态
meHands?: HandState; // 自己的手牌
opHands?: HandState; // 对手的手牌
meMonsters?: MonsterState; // 自己的怪兽区状态
opMonsters?: MonsterState; // 对手的怪兽区状态
meMagics?: MagicState; // 自己的魔法陷阱区状态
opMagics?: MagicState; // 对手的魔法陷阱区状态
meGraveyard?: GraveyardState; // 自己的墓地状态
opGraveyard?: GraveyardState; // 对手的墓地状态
meBanishedZone?: BanishedZoneState; // 自己的除外区状态
opBanishedZone?: BanishedZoneState; // 对手的除外区状态
meDeck?: DeckState; // 自己的卡组状态
opDeck?: DeckState; // 对手的卡组状态
meExtraDeck?: ExtraDeckState; // 自己的额外卡组状态
opExtraDeck?: ExtraDeckState; // 对手的额外卡组状态
meTimeLimit?: TimeLimit; // 自己的计时
opTimeLimit?: TimeLimit; // 对手的计时
hint?: HintState;
currentPlayer?: number; // 当前的操作方
phase?: PhaseState;
result?: MsgWin.ActionType;
waiting?: boolean;
unimplemented?: number; // 未处理的`Message`
// UI相关
modalState: ModalState;
}
const initialState: DuelState = {
modalState: {
cardModal: { isOpen: false, interactivies: [], counters: {} },
cardListModal: { isOpen: false, list: [] },
checkCardModal: { isOpen: false, cancelAble: false, tags: [] },
yesNoModal: { isOpen: false },
positionModal: { isOpen: false, positions: [] },
optionModal: { isOpen: false, options: [] },
checkCardModalV2: {
isOpen: false,
cancelAble: false,
finishAble: false,
responseable: false,
selectableOptions: [],
selectedOptions: [],
},
checkCardModalV3: {
isOpen: false,
overflow: false,
allLevel: 0,
mustSelectList: [],
selectAbleList: [],
},
checkCounterModal: {
isOpen: false,
options: [],
},
sortCardModal: {
isOpen: false,
options: [],
},
},
};
const duelSlice = createSlice({
name: "duel",
initialState,
reducers: {
setSelfType: (state, action: PayloadAction<number>) => {
state.selfType = action.payload;
},
infoInit: infoInitImpl,
updateHp: updateHpImpl,
updateTurn: newTurnImpl,
updateTimeLimit: updateTimeLimitImpl,
// 手牌相关`Reducer`
clearHandsIdleInteractivity: clearHandsIdleInteractivityImpl,
addHandsIdleInteractivity: addHandsIdleInteractivityImpl,
removeHand: removeHandImpl,
// 怪兽区相关`Reducer`
initMonsters: initMonstersImpl,
addMonsterPlaceInteractivities: addMonsterPlaceInteractivitiesImpl,
clearMonsterPlaceInteractivities: clearMonsterPlaceInteractivitiesImpl,
addMonsterIdleInteractivities: addMonsterIdleInteractivitiesImpl,
clearMonsterIdleInteractivities: clearMonsterIdleInteractivitiesImpl,
setMonsterPosition: setMonsterPositionImpl,
removeMonster: removeMonsterImpl,
removeOverlay: removeOverlayImpl,
updateMonsterCounters: updateMonsterCountersImpl,
// 魔法陷阱区相关`Reducer`
initMagics: initMagicsImpl,
addMagicPlaceInteractivities: addMagicPlaceInteractivitiesImpl,
clearMagicPlaceInteractivities: clearMagicPlaceInteractivitiesImpl,
addMagicIdleInteractivities: addMagicIdleInteractivitiesImpl,
clearMagicIdleInteractivities: clearMagicIdleInteractivitiesImpl,
setMagicPosition: setMagicPositionImpl,
removeMagic: removeMagicImpl,
// 墓地相关`Reducer`
initGraveyard: initGraveyardImpl,
removeGraveyard: removeGraveyardImpl,
addGraveyardIdleInteractivities: addGraveyardIdleInteractivitiesImpl,
// 除外区相关`Reducer`
initBanishedZone: initBanishedZoneImpl,
removeBanishedZone: removeBanishedZoneImpl,
addBanishedZoneIdleInteractivities: addBanishedZoneIdleInteractivitiesImpl,
// 卡组相关`Reducer`
initDeck: initDeckImpl,
// 额外卡组相关`Reducer`
removeExtraDeck: removeExtraDeckImpl,
addExtraDeckIdleInteractivities: addExtraDeckIdleInteractivitiesImpl,
// 阶段相关
updatePhase: newPhaseImpl,
setEnableBp: setEnableBpImpl,
setEnableM2: setEnableM2Impl,
setEnableEp: setEnableEpImpl,
// UI相关`Reducer`
setCardModalIsOpen: setCardModalIsOpenImpl,
setCardModalMeta: setCardModalMetaImpl,
setCardModalInteractivies: setCardModalInteractiviesImpl,
setCardListModalIsOpen: setCardListModalIsOpenImpl,
setCardListModalInfo: setCardListModalInfoImpl,
setCheckCardModalIsOpen: setCheckCardModalIsOpenImpl,
setCheckCardModalMinMax: setCheckCardModalMinMaxImpl,
setCheckCardModalOnSubmit: setCheckCardModalOnSubmitImpl,
setCheckCardMOdalCancelAble: setCheckCardMOdalCancelAbleImpl,
setCheckCardModalCancelResponse: setCheckCardModalCancelResponseImpl,
resetCheckCardModal: resetCheckCardModalImpl,
setYesNoModalIsOpen: setYesNoModalIsOpenImpl,
setPositionModalIsOpen: setPositionModalIsOpenImpl,
setPositionModalPositions: setPositionModalPositionsImpl,
resetPositionModal: resetPositionModalImpl,
setOptionModalIsOpen: setOptionModalIsOpenImpl,
resetOptionModal: resetOptionModalImpl,
setCheckCardModalV2FinishAble: setCheckCardModalV2FinishAbleImpl,
setCheckCardModalV2MinMax: setCheckCardModalV2MinMaxImpl,
setCheckCardModalV2CancelAble: setCheckCardModalV2CancelAbleImpl,
setCheckCardModalV2IsOpen: setCheckCardModalV2IsOpenImpl,
resetCheckCardModalV2: resetCheckCardModalV2Impl,
setCheckCardModalV2ResponseAble: setCheckCardModalV2ResponseAbleImpl,
setCheckCardModalV3IsOpen: setCheckCardModalV3IsOpenImpl,
setCheckCardModalV3MinMax: setCheckCardModalV3MinMaxImpl,
setCheckCardModalV3AllLevel: setCheckCardModalV3AllLevelImpl,
setCheckCardModalV3OverFlow: setCheckCardModalV3OverFlowImpl,
setCheckCardModalV3ResponseAble: setCheckCardModalV3ResponseAbleImpl,
resetCheckCardModalV3: resetCheckCardModalV3Impl,
setCardModalCounters: setCardModalCountersImpl,
setCheckCounter: setCheckCounterImpl,
clearCheckCounter: clearCheckCounterImpl,
setSortCardModalIsOpen: setSortCardModalIsOpenImpl,
resetSortCardModal: resetSortCardModalImpl,
// 提示相关`Reducer`
initHint: initHintImpl,
// 通用的`Reducer`
clearAllIdleInteractivities: clearAllIdleInteractivitiesImpl,
clearAllPlaceInteractivities: clearAllPlaceInteractivitiesImpl,
updateFieldData: updateFieldDataImpl,
reloadField: reloadFieldImpl,
// 对局结果`Reducer`
setResult: (state, action: PayloadAction<MsgWin.ActionType>) => {
state.result = action.payload;
},
// 等待状态`Reducer`
setWaiting: (state, action: PayloadAction<boolean>) => {
state.waiting = action.payload;
},
// 未处理状态`Reducer`
setUnimplemented: (state, action: PayloadAction<number>) => {
state.unimplemented = action.payload;
},
},
extraReducers(builder) {
handsCase(builder);
hintCase(builder);
monsterCase(builder);
magicCase(builder);
graveyardCase(builder);
banishedZoneCase(builder);
extraDeckCase(builder);
checkCardModalCase(builder);
YesNoModalCase(builder);
optionModalCase(builder);
checkCardModalV2Case(builder);
checkCardModalV3Case(builder);
sortCardModalCase(builder);
},
});
export const {
setSelfType,
infoInit,
updateHp,
updateTurn,
updatePhase,
setEnableBp,
setEnableM2,
setEnableEp,
clearHandsIdleInteractivity,
addHandsIdleInteractivity,
updateTimeLimit,
setCardModalIsOpen,
setCardModalMeta,
setCardModalInteractivies,
initMonsters,
addMonsterPlaceInteractivities,
clearMonsterPlaceInteractivities,
addMonsterIdleInteractivities,
clearMonsterIdleInteractivities,
setMonsterPosition,
removeMonster,
updateMonsterCounters,
removeOverlay,
initMagics,
addMagicPlaceInteractivities,
clearMagicPlaceInteractivities,
addMagicIdleInteractivities,
clearMagicIdleInteractivities,
setMagicPosition,
removeMagic,
removeHand,
initGraveyard,
removeGraveyard,
addGraveyardIdleInteractivities,
setCardListModalIsOpen,
setCardListModalInfo,
setCheckCardModalIsOpen,
setCheckCardModalMinMax,
setCheckCardModalOnSubmit,
setCheckCardMOdalCancelAble,
setCheckCardModalCancelResponse,
resetCheckCardModal,
setYesNoModalIsOpen,
setPositionModalIsOpen,
setPositionModalPositions,
resetPositionModal,
setOptionModalIsOpen,
resetOptionModal,
initDeck,
removeExtraDeck,
addExtraDeckIdleInteractivities,
initBanishedZone,
removeBanishedZone,
addBanishedZoneIdleInteractivities,
setCheckCardModalV2IsOpen,
setCheckCardModalV2MinMax,
setCheckCardModalV2CancelAble,
setCheckCardModalV2FinishAble,
resetCheckCardModalV2,
setCheckCardModalV2ResponseAble,
clearAllIdleInteractivities,
clearAllPlaceInteractivities,
setResult,
setWaiting,
setUnimplemented,
updateFieldData,
reloadField,
setCheckCardModalV3IsOpen,
setCheckCardModalV3MinMax,
setCheckCardModalV3AllLevel,
setCheckCardModalV3OverFlow,
setCheckCardModalV3ResponseAble,
resetCheckCardModalV3,
setCardModalCounters,
setCheckCounter,
clearCheckCounter,
setSortCardModalIsOpen,
resetSortCardModal,
initHint,
} = duelSlice.actions;
export const selectDuelHsStart = (state: RootState) => {
return state.duel.meInitInfo != null;
};
export const selectDuelResult = (state: RootState) => {
return state.duel.result;
};
export const selectWaiting = (state: RootState) => {
return state.duel.waiting;
};
export const selectUnimplemented = (state: RootState) => {
return state.duel.unimplemented;
};
export default duelSlice.reducer;
import { CaseReducer, PayloadAction } from "@reduxjs/toolkit";
import { CardMeta } from "@/api/cards";
import { RootState } from "@/store";
import { DuelState } from "../mod";
// 更新卡牌列表弹窗打开状态
export const setCardListModalIsOpenImpl: CaseReducer<
DuelState,
PayloadAction<boolean>
> = (state, action) => {
state.modalState.cardListModal.isOpen = action.payload;
};
// 更新卡牌列表数据
export const setCardListModalInfoImpl: CaseReducer<
DuelState,
PayloadAction<
{
meta?: CardMeta;
interactivies: { desc: string; response: number }[];
}[]
>
> = (state, action) => {
const list = action.payload;
state.modalState.cardListModal.list = list;
};
export const selectCardListModalIsOpen = (state: RootState) =>
state.duel.modalState.cardListModal.isOpen;
export const selectCardListModalInfo = (state: RootState) =>
state.duel.modalState.cardListModal.list;
import { CaseReducer, PayloadAction } from "@reduxjs/toolkit";
import { CardMeta } from "@/api/cards";
import { RootState } from "@/store";
import { DuelState } from "../mod";
// 更新卡牌弹窗打开状态
export const setCardModalIsOpenImpl: CaseReducer<
DuelState,
PayloadAction<boolean>
> = (state, action) => {
state.modalState.cardModal.isOpen = action.payload;
};
// 更新卡牌弹窗文本
export const setCardModalMetaImpl: CaseReducer<
DuelState,
PayloadAction<CardMeta>
> = (state, action) => {
state.modalState.cardModal.meta = action.payload;
};
// 更新卡牌弹窗互动选项
export const setCardModalInteractiviesImpl: CaseReducer<
DuelState,
PayloadAction<{ desc: string; response: number }[]>
> = (state, action) => {
state.modalState.cardModal.interactivies = action.payload;
};
// 更新卡牌弹窗指示器
export const setCardModalCountersImpl: CaseReducer<
DuelState,
PayloadAction<{ [type: number]: number }>
> = (state, action) => {
state.modalState.cardModal.counters = action.payload;
};
export const selectCardModalIsOpen = (state: RootState) =>
state.duel.modalState.cardModal.isOpen;
export const selectCardModalMeta = (state: RootState) =>
state.duel.modalState.cardModal.meta;
export const selectCardModalInteractivies = (state: RootState) =>
state.duel.modalState.cardModal.interactivies;
export const selectCardModalCounters = (state: RootState) =>
state.duel.modalState.cardModal.counters;
import {
ActionReducerMapBuilder,
CaseReducer,
createAsyncThunk,
PayloadAction,
} from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { fetchCard, getCardStr } from "@/api/cards";
import { RootState } from "@/store";
import { DuelState } from "../mod";
import { cmpCardLocation, findCardByLocation, judgeSelf } from "../util";
// 更新卡牌选择弹窗打开状态
export const setCheckCardModalIsOpenImpl: CaseReducer<
DuelState,
PayloadAction<boolean>
> = (state, action) => {
state.modalState.checkCardModal.isOpen = action.payload;
};
// 更新卡牌选择弹窗选择数目状态
export const setCheckCardModalMinMaxImpl: CaseReducer<
DuelState,
PayloadAction<{ min: number; max: number }>
> = (state, action) => {
state.modalState.checkCardModal.selectMin = action.payload.min;
state.modalState.checkCardModal.selectMax = action.payload.max;
};
// 更新卡牌选择弹窗的提交回调
export const setCheckCardModalOnSubmitImpl: CaseReducer<
DuelState,
PayloadAction<string>
> = (state, action) => {
state.modalState.checkCardModal.onSubmit = action.payload;
};
// 更新卡牌选择弹窗是否可以取消
export const setCheckCardMOdalCancelAbleImpl: CaseReducer<
DuelState,
PayloadAction<boolean>
> = (state, action) => {
state.modalState.checkCardModal.cancelAble = action.payload;
};
// 更新卡牌选择弹窗取消时返回给服务端的`Response`
export const setCheckCardModalCancelResponseImpl: CaseReducer<
DuelState,
PayloadAction<number>
> = (state, action) => {
state.modalState.checkCardModal.cancelResponse = action.payload;
};
// 增加卡牌选择选项
export const fetchCheckCardMeta = createAsyncThunk(
"duel/fetchCheckCardMeta",
async (param: {
tagName: string;
option: {
code: number;
location: ygopro.CardLocation;
response: number;
effectDescCode?: number;
};
}) => {
// FIXME: 这里如果传的`controler`如果是对手,对应的`code`会为零,这时候就无法更新对应的`Meta`信息了,后续需要修复。`fetchCheckCardMetaV2`和`fetchCheckCardMetaV3`同理
const meta = await fetchCard(param.option.code, true);
const response = {
tagName: param.tagName,
option: {
meta,
location: param.option.location.toObject(),
},
};
return response;
}
);
export const checkCardModalCase = (
builder: ActionReducerMapBuilder<DuelState>
) => {
builder.addCase(fetchCheckCardMeta.pending, (state, action) => {
const tagName = action.meta.arg.tagName;
const code = action.meta.arg.option.code;
const location = action.meta.arg.option.location;
const controler = location.controler;
const effectDescCode = action.meta.arg.option.effectDescCode;
const response = action.meta.arg.option.response;
const combinedTagName = judgeSelf(controler, state)
? `我方的${tagName}`
: `对方的${tagName}`;
const newID =
code != 0 ? code : findCardByLocation(state, location)?.occupant?.id || 0;
const newOption = {
meta: { id: newID, data: {}, text: {} },
location: location.toObject(),
effectDescCode,
response,
};
for (const tag of state.modalState.checkCardModal.tags) {
if (tag.tagName === combinedTagName) {
tag.options.push(newOption);
return;
}
}
state.modalState.checkCardModal.tags.push({
tagName: combinedTagName,
options: [newOption],
});
});
builder.addCase(fetchCheckCardMeta.fulfilled, (state, action) => {
const tagName = action.payload.tagName;
const option = action.payload.option;
const controler = option.location.controler!;
const combinedTagName = judgeSelf(controler, state)
? `我方的${tagName}`
: `对方的${tagName}`;
for (const tag of state.modalState.checkCardModal.tags) {
if (tag.tagName === combinedTagName) {
for (const old of tag.options) {
if (
option.meta.id == old.meta.id &&
cmpCardLocation(option.location, old.location)
) {
const cardID = old.meta.id;
old.meta = option.meta;
old.meta.id = cardID;
const effectDescCode = old.effectDescCode;
const effectDesc = effectDescCode
? getCardStr(old.meta, effectDescCode & 0xf)
: undefined;
old.effectDesc = effectDesc;
}
}
}
}
});
};
export const resetCheckCardModalImpl: CaseReducer<DuelState> = (state) => {
state.modalState.checkCardModal.isOpen = false;
state.modalState.checkCardModal.selectMin = undefined;
state.modalState.checkCardModal.selectMax = undefined;
state.modalState.checkCardModal.cancelAble = false;
state.modalState.checkCardModal.cancelResponse = undefined;
state.modalState.checkCardModal.tags = [];
};
export const selectCheckCardModalIsOpen = (state: RootState) =>
state.duel.modalState.checkCardModal.isOpen;
export const selectCheckCardModalMinMax = (state: RootState) => {
return {
min: state.duel.modalState.checkCardModal.selectMin || 0,
max: state.duel.modalState.checkCardModal.selectMax || 0,
};
};
export const selectCheckCardModalTags = (state: RootState) =>
state.duel.modalState.checkCardModal.tags;
export const selectCheckCardModalOnSubmit = (state: RootState) =>
state.duel.modalState.checkCardModal.onSubmit;
export const selectCheckCardModalCancelAble = (state: RootState) =>
state.duel.modalState.checkCardModal.cancelAble;
export const selectCheckCardModalCacnelResponse = (state: RootState) =>
state.duel.modalState.checkCardModal.cancelResponse;
import {
ActionReducerMapBuilder,
CaseReducer,
createAsyncThunk,
} from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { fetchCard } from "@/api/cards";
import { RootState } from "@/store";
import { DuelReducer } from "../generic";
import { DuelState } from "../mod";
import { findCardByLocation } from "../util";
// 更新打开状态
export const setCheckCardModalV2IsOpenImpl: DuelReducer<boolean> = (
state,
action
) => {
state.modalState.checkCardModalV2.isOpen = action.payload;
};
// 更新选择数目
export const setCheckCardModalV2MinMaxImpl: DuelReducer<{
min: number;
max: number;
}> = (state, action) => {
state.modalState.checkCardModalV2.selectMin = action.payload.min;
state.modalState.checkCardModalV2.selectMax = action.payload.max;
};
// 更新是否可以取消
export const setCheckCardModalV2CancelAbleImpl: DuelReducer<boolean> = (
state,
action
) => {
state.modalState.checkCardModalV2.cancelAble = action.payload;
};
// 更新是否可以结束
export const setCheckCardModalV2FinishAbleImpl: DuelReducer<boolean> = (
state,
action
) => {
state.modalState.checkCardModalV2.finishAble = action.payload;
};
// 更新是否可以回应
export const setCheckCardModalV2ResponseAbleImpl: DuelReducer<boolean> = (
state,
action
) => {
state.modalState.checkCardModalV2.responseable = action.payload;
};
// 增加卡牌选项
export const fetchCheckCardMetasV2 = createAsyncThunk(
"duel/fetchCheckCardMetaV2",
async (param: {
selected: boolean;
options: {
code: number;
location: ygopro.CardLocation;
response: number;
}[];
}) => {
const metas = await Promise.all(
param.options.map(async (option) => {
return await fetchCard(option.code, true);
})
);
const response = {
selected: param.selected,
metas,
};
return response;
}
);
export const checkCardModalV2Case = (
builder: ActionReducerMapBuilder<DuelState>
) => {
builder.addCase(fetchCheckCardMetasV2.pending, (state, action) => {
const selected = action.meta.arg.selected;
const options = action.meta.arg.options;
for (const option of options) {
if (option.code == 0) {
const newCode =
findCardByLocation(state, option.location)?.occupant?.id || 0;
option.code = newCode;
}
}
if (selected) {
state.modalState.checkCardModalV2.selectedOptions = options;
} else {
state.modalState.checkCardModalV2.selectableOptions = options;
}
});
builder.addCase(fetchCheckCardMetasV2.fulfilled, (state, action) => {
const selected = action.payload.selected;
const metas = action.payload.metas;
const options = selected
? state.modalState.checkCardModalV2.selectedOptions
: state.modalState.checkCardModalV2.selectableOptions;
options.forEach((option) => {
metas.forEach((meta) => {
if (option.code == meta.id) {
option.name = meta.text.name;
option.desc = meta.text.desc;
}
});
});
});
};
export const resetCheckCardModalV2Impl: CaseReducer<DuelState> = (state) => {
const modalState = state.modalState.checkCardModalV2;
modalState.isOpen = false;
modalState.finishAble = false;
modalState.cancelAble = false;
modalState.responseable = false;
modalState.selectableOptions = [];
modalState.selectedOptions = [];
};
export const selectCheckCardModalV2IsOpen = (state: RootState) =>
state.duel.modalState.checkCardModalV2.isOpen;
export const selectCheckCardModalV2MinMax = (state: RootState) => {
return {
min: state.duel.modalState.checkCardModalV2.selectMin || 0,
max: state.duel.modalState.checkCardModalV2.selectMax || 0,
};
};
export const selectCheckCardModalV2CancelAble = (state: RootState) =>
state.duel.modalState.checkCardModalV2.cancelAble;
export const selectCheckCardModalV2FinishAble = (state: RootState) =>
state.duel.modalState.checkCardModalV2.finishAble;
export const selectCheckCardModalV2ResponseAble = (state: RootState) =>
state.duel.modalState.checkCardModalV2.responseable;
export const selectCheckCardModalV2SelectAbleOptions = (state: RootState) =>
state.duel.modalState.checkCardModalV2.selectableOptions;
export const selectCheckCardModalV2SelectedOptions = (state: RootState) =>
state.duel.modalState.checkCardModalV2.selectedOptions;
import {
ActionReducerMapBuilder,
CaseReducer,
createAsyncThunk,
} from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { fetchCard } from "@/api/cards";
import { RootState } from "@/store";
import { DuelReducer } from "../generic";
import { DuelState } from "../mod";
import { findCardByLocation } from "../util";
// 更新打开状态
export const setCheckCardModalV3IsOpenImpl: DuelReducer<boolean> = (
state,
action
) => {
state.modalState.checkCardModalV3.isOpen = action.payload;
};
// 更新选择数目
export const setCheckCardModalV3MinMaxImpl: DuelReducer<{
min: number;
max: number;
}> = (state, action) => {
state.modalState.checkCardModalV3.selectMin = action.payload.min;
state.modalState.checkCardModalV3.selectMax = action.payload.max;
};
export const setCheckCardModalV3AllLevelImpl: DuelReducer<number> = (
state,
action
) => {
state.modalState.checkCardModalV3.allLevel = action.payload;
};
export const setCheckCardModalV3OverFlowImpl: DuelReducer<boolean> = (
state,
action
) => {
state.modalState.checkCardModalV3.overflow = action.payload;
};
export const setCheckCardModalV3ResponseAbleImpl: DuelReducer<boolean> = (
state,
action
) => {
state.modalState.checkCardModalV3.responseable = action.payload;
};
// 增加卡牌选项
export const fetchCheckCardMetasV3 = createAsyncThunk(
"duel/fetchCheckCardMetaV3",
async (param: {
mustSelect: boolean;
options: {
code: number;
location: ygopro.CardLocation;
level1: number;
level2: number;
response: number;
}[];
}) => {
const metas = await Promise.all(
param.options.map(async (option) => {
return await fetchCard(option.code, true);
})
);
const response = {
mustSelect: param.mustSelect,
metas,
};
return response;
}
);
export const checkCardModalV3Case = (
builder: ActionReducerMapBuilder<DuelState>
) => {
builder.addCase(fetchCheckCardMetasV3.pending, (state, action) => {
const mustSelect = action.meta.arg.mustSelect;
const options = action.meta.arg.options.map((option) => {
if (option.code == 0) {
const newCode =
findCardByLocation(state, option.location)?.occupant?.id || 0;
option.code = newCode;
}
return {
meta: { id: option.code, data: {}, text: {} },
level1: option.level1,
level2: option.level2,
response: option.response,
};
});
if (mustSelect) {
state.modalState.checkCardModalV3.mustSelectList = options;
} else {
state.modalState.checkCardModalV3.selectAbleList = options;
}
});
builder.addCase(fetchCheckCardMetasV3.fulfilled, (state, action) => {
const mustSelect = action.payload.mustSelect;
const metas = action.payload.metas;
const options = mustSelect
? state.modalState.checkCardModalV3.mustSelectList
: state.modalState.checkCardModalV3.selectAbleList;
options.forEach((option) => {
metas.forEach((meta) => {
if (option.meta.id == meta.id) {
option.meta = meta;
}
});
});
});
};
export const resetCheckCardModalV3Impl: CaseReducer<DuelState> = (state) => {
const modalState = state.modalState.checkCardModalV3;
modalState.isOpen = false;
modalState.overflow = false;
modalState.allLevel = 0;
modalState.responseable = undefined;
modalState.mustSelectList = [];
modalState.selectAbleList = [];
};
export const selectCheckCardModalV3 = (state: RootState) =>
state.duel.modalState.checkCardModalV3;
// 后续对于`MSG_SELECT_XXX`的处理UI都尽量用`Babylon.js`实现而不会通过`Antd`的`Modal`实现,因此这里不追求工程质量,暂时简单实现下。
import { CaseReducer, PayloadAction } from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { RootState } from "@/store";
import { DuelState } from "../mod";
import { findCardByLocation } from "../util";
type SelectCounter = ReturnType<
typeof ygopro.StocGameMessage.MsgSelectCounter.prototype.toObject
>;
export const setCheckCounterImpl: CaseReducer<
DuelState,
PayloadAction<SelectCounter>
> = (state, action) => {
const modal = state.modalState.checkCounterModal;
const payload = action.payload;
modal.counterType = payload.counter_type;
modal.min = payload.min;
modal.options = payload.options!.map((option) => {
const code = option.code
? option.code
: findCardByLocation(state, option.location!)?.occupant?.id || 0;
return {
code,
max: option.counter_count!,
};
});
modal.isOpen = true;
};
export const clearCheckCounterImpl: CaseReducer<DuelState> = (state) => {
state.modalState.checkCounterModal.isOpen = false;
state.modalState.checkCounterModal.min = undefined;
state.modalState.checkCounterModal.counterType = undefined;
state.modalState.checkCounterModal.options = [];
};
export const selectCheckCounterModal = (state: RootState) =>
state.duel.modalState.checkCounterModal;
import { ygopro } from "@/api";
import { CardMeta } from "@/api/cards";
type CardLocation = ReturnType<typeof ygopro.CardLocation.prototype.toObject>;
export interface ModalState {
// 卡牌弹窗
cardModal: {
isOpen: boolean;
meta?: CardMeta;
interactivies: { desc: string; response: number }[];
counters: { [type: number]: number };
};
// 卡牌列表弹窗
cardListModal: {
isOpen: boolean;
list: {
meta?: CardMeta;
interactivies: { desc: string; response: number }[];
}[];
};
// 卡牌选择弹窗
checkCardModal: {
isOpen: boolean;
onSubmit?: string;
selectMin?: number;
selectMax?: number;
cancelAble: boolean;
cancelResponse?: number;
tags: {
tagName: string;
options: {
meta: CardMeta;
location?: CardLocation;
effectDescCode?: number;
effectDesc?: string;
response: number;
}[];
}[];
};
// Yes or No弹窗
yesNoModal: {
isOpen: boolean;
msg?: string;
};
// 表示形式选择弹窗
positionModal: {
isOpen: boolean;
positions: ygopro.CardPosition[];
};
// 选项选择弹窗
optionModal: {
isOpen: boolean;
options: { msg: string; response: number }[];
};
// 卡牌选择弹窗V2
checkCardModalV2: {
isOpen: boolean;
cancelAble: boolean;
finishAble: boolean;
selectMin?: number;
selectMax?: number;
responseable?: boolean;
selectableOptions: {
code: number;
name?: string;
desc?: string;
response: number;
}[];
selectedOptions: {
code: number;
name?: string;
desc?: string;
response: number;
}[];
};
// 卡牌选择弹窗V3
checkCardModalV3: {
isOpen: boolean;
overflow: boolean;
allLevel: number;
selectMin?: number;
selectMax?: number;
responseable?: boolean;
mustSelectList: {
meta: CardMeta;
level1: number;
level2: number;
response: number;
}[];
selectAbleList: {
meta: CardMeta;
level1: number;
level2: number;
response: number;
}[];
};
// 指示器选择弹窗
checkCounterModal: {
isOpen: boolean;
counterType?: number;
min?: number;
options: {
code: number;
max: number;
}[];
};
// 卡牌排序弹窗
sortCardModal: {
isOpen: boolean;
options: {
meta: CardMeta;
response: number;
}[];
};
}
export * from "./cardListModalSlice";
export * from "./cardModalSlice";
export * from "./checkCardModalSlice";
export * from "./checkCardModalV2Slice";
export * from "./checkCardModalV3Slice";
export * from "./checkCounterModalSlice";
export * from "./optionModalSlice";
export * from "./positionModalSlice";
export * from "./sortCardModalSlice";
export * from "./yesNoModalSlice";
import {
ActionReducerMapBuilder,
CaseReducer,
createAsyncThunk,
PayloadAction,
} from "@reduxjs/toolkit";
import { fetchCard, getCardStr } from "@/api/cards";
import { RootState } from "@/store";
import { DuelState } from "../mod";
export const setOptionModalIsOpenImpl: CaseReducer<
DuelState,
PayloadAction<boolean>
> = (state, action) => {
state.modalState.optionModal.isOpen = action.payload;
};
export const resetOptionModalImpl: CaseReducer<DuelState> = (state) => {
state.modalState.optionModal.options = [];
};
// 增加选项
export const fetchOptionMeta = createAsyncThunk(
"duel/fetchOptionMeta",
async (param: { code: number; response: number }) => {
const meta = await fetchCard(param.code >> 4, true);
const msg = getCardStr(meta, param.code & 0xf) || "[?]";
const response = { msg, response: param.response };
return response;
}
);
export const optionModalCase = (
builder: ActionReducerMapBuilder<DuelState>
) => {
builder.addCase(fetchOptionMeta.fulfilled, (state, action) => {
state.modalState.optionModal.options.push(action.payload);
});
};
export const selectOptionModalIsOpen = (state: RootState) =>
state.duel.modalState.optionModal.isOpen;
export const selectOptionModalOptions = (state: RootState) =>
state.duel.modalState.optionModal.options;
import { CaseReducer, PayloadAction } from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { RootState } from "@/store";
import { DuelState } from "../mod";
export const setPositionModalIsOpenImpl: CaseReducer<
DuelState,
PayloadAction<boolean>
> = (state, action) => {
state.modalState.positionModal.isOpen = action.payload;
};
export const setPositionModalPositionsImpl: CaseReducer<
DuelState,
PayloadAction<ygopro.CardPosition[]>
> = (state, action) => {
state.modalState.positionModal.positions = action.payload;
};
export const resetPositionModalImpl: CaseReducer<DuelState> = (state) => {
state.modalState.positionModal.isOpen = false;
state.modalState.positionModal.positions = [];
};
export const selectPositionModalIsOpen = (state: RootState) =>
state.duel.modalState.positionModal.isOpen;
export const selectPositionModalPositions = (state: RootState) =>
state.duel.modalState.positionModal.positions;
import {
ActionReducerMapBuilder,
CaseReducer,
createAsyncThunk,
} from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { fetchCard } from "@/api/cards";
import { RootState } from "@/store";
import { DuelReducer } from "../generic";
import { DuelState } from "../mod";
type SortCard = ReturnType<
typeof ygopro.StocGameMessage.MsgSortCard.Info.prototype.toObject
>;
export const setSortCardModalIsOpenImpl: DuelReducer<boolean> = (
state,
action
) => {
state.modalState.sortCardModal.isOpen = action.payload;
};
export const resetSortCardModalImpl: CaseReducer<DuelState> = (state) => {
state.modalState.sortCardModal.isOpen = false;
state.modalState.sortCardModal.options = [];
};
export const fetchSortCardMeta = createAsyncThunk(
"duel/fetchSortCardMeta",
async (param: SortCard) => {
const meta = await fetchCard(param.code!, true);
return {
meta,
response: param.response!,
};
}
);
export const sortCardModalCase = (
builder: ActionReducerMapBuilder<DuelState>
) => {
// 这里更合理的做法是`pending`的时候先更新`options`,等`meta`数据返回后再异步更新`meta`
builder.addCase(fetchSortCardMeta.fulfilled, (state, action) => {
state.modalState.sortCardModal.options.push(action.payload);
});
};
export const selectSortCardModal = (state: RootState) =>
state.duel.modalState.sortCardModal;
import {
ActionReducerMapBuilder,
CaseReducer,
createAsyncThunk,
PayloadAction,
} from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { CardMeta, fetchCard } from "@/api/cards";
import { fetchStrings, getStrings } from "@/api/strings";
import { RootState } from "@/store";
import { DuelState } from "../mod";
// 更新YesNo弹窗是否打开状态
export const setYesNoModalIsOpenImpl: CaseReducer<
DuelState,
PayloadAction<boolean>
> = (state, action) => {
state.modalState.yesNoModal.isOpen = action.payload;
};
// 设置YesNo弹窗展示内容
export const fetchYesNoMeta = createAsyncThunk(
"duel/fetchYesNoMeta",
async (param: {
code: number;
location: ygopro.CardLocation;
descCode: number;
textGenerator: (
desc: string,
cardMeta: CardMeta,
cardLocation: ygopro.CardLocation
) => string;
}) => {
const desc = fetchStrings("!system", param.descCode);
const meta = await fetchCard(param.code, true);
// TODO: 国际化文案
return param.textGenerator(desc, meta, param.location);
}
);
export const fetchYesNoMetaWithEffecDesc = createAsyncThunk(
"duel/fetchYesNoMetaWithEffecDesc",
async (effectDesc: number) => {
return getStrings(effectDesc);
}
);
export const YesNoModalCase = (builder: ActionReducerMapBuilder<DuelState>) => {
builder.addCase(fetchYesNoMeta.fulfilled, (state, action) => {
state.modalState.yesNoModal.msg = action.payload;
});
builder.addCase(fetchYesNoMetaWithEffecDesc.fulfilled, (state, action) => {
state.modalState.yesNoModal.msg = action.payload;
});
};
export const selectYesNoModalIsOpen = (state: RootState) =>
state.duel.modalState.yesNoModal.isOpen;
export const selectYesNOModalMsg = (state: RootState) =>
state.duel.modalState.yesNoModal.msg;
import {
ActionReducerMapBuilder,
CaseReducer,
createAsyncThunk,
PayloadAction,
} from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { fetchCard } from "@/api/cards";
import { RootState } from "@/store";
import {
clearIdleInteractivities,
clearPlaceInteractivities,
createAsyncMetaThunk,
DuelFieldState,
extendIdleInteractivities,
extendOccupant,
extendPlaceInteractivity,
Interactivity,
removeOccupant,
removeOverlay,
setPosition,
} from "./generic";
import { DuelState } from "./mod";
import { judgeSelf } from "./util";
type MsgUpdateCounter = ReturnType<
typeof ygopro.StocGameMessage.MsgUpdateCounter.prototype.toObject
>;
export interface MonsterState extends DuelFieldState {}
// 初始化怪兽区状态
export const initMonstersImpl: CaseReducer<DuelState, PayloadAction<number>> = (
state,
action
) => {
const player = action.payload;
const monsters = {
inner: [
{
location: {
controler: player,
location: ygopro.CardZone.MZONE,
},
idleInteractivities: [],
counters: {},
},
{
location: {
controler: player,
location: ygopro.CardZone.MZONE,
},
idleInteractivities: [],
counters: {},
},
{
location: {
controler: player,
location: ygopro.CardZone.MZONE,
},
idleInteractivities: [],
counters: {},
},
{
location: {
controler: player,
location: ygopro.CardZone.MZONE,
},
idleInteractivities: [],
counters: {},
},
{
location: {
controler: player,
location: ygopro.CardZone.MZONE,
},
idleInteractivities: [],
counters: {},
},
{
location: {
controler: player,
location: ygopro.CardZone.MZONE,
},
idleInteractivities: [],
counters: {},
},
{
location: {
controler: player,
location: ygopro.CardZone.MZONE,
},
idleInteractivities: [],
counters: {},
},
],
};
if (judgeSelf(player, state)) {
state.meMonsters = monsters;
} else {
state.opMonsters = monsters;
}
};
export const addMonsterPlaceInteractivitiesImpl: CaseReducer<
DuelState,
PayloadAction<[number, number]>
> = (state, action) => {
const controler = action.payload[0];
const sequence = action.payload[1];
const monsters = judgeSelf(controler, state)
? state.meMonsters
: state.opMonsters;
extendPlaceInteractivity(
monsters,
controler,
sequence,
ygopro.CardZone.MZONE
);
};
export const clearMonsterPlaceInteractivitiesImpl: CaseReducer<
DuelState,
PayloadAction<number>
> = (state, action) => {
const player = action.payload;
const monsters = judgeSelf(player, state)
? state.meMonsters
: state.opMonsters;
clearPlaceInteractivities(monsters);
};
export const addMonsterIdleInteractivitiesImpl: CaseReducer<
DuelState,
PayloadAction<{
player: number;
sequence: number;
interactivity: Interactivity<number>;
}>
> = (state, action) => {
const monsters = judgeSelf(action.payload.player, state)
? state.meMonsters
: state.opMonsters;
extendIdleInteractivities(
monsters,
action.payload.sequence,
action.payload.interactivity
);
};
export const updateMonsterCountersImpl: CaseReducer<
DuelState,
PayloadAction<MsgUpdateCounter>
> = (state, action) => {
const monsters = judgeSelf(action.payload.location?.controler!, state)
? state.meMonsters
: state.opMonsters;
if (monsters) {
const target = monsters.inner.find(
(_, idx) => idx == action.payload.location?.sequence!
);
if (target) {
const count = action.payload.count!;
const counterType = action.payload.action_type!;
switch (action.payload.action_type!) {
case ygopro.StocGameMessage.MsgUpdateCounter.ActionType.ADD: {
if (counterType in target.counters) {
target.counters[counterType] += count;
} else {
target.counters[counterType] = count;
}
break;
}
case ygopro.StocGameMessage.MsgUpdateCounter.ActionType.REMOVE: {
if (counterType in target.counters) {
target.counters[counterType] -= count;
}
break;
}
default: {
break;
}
}
}
}
};
export const clearMonsterIdleInteractivitiesImpl: CaseReducer<
DuelState,
PayloadAction<number>
> = (state, action) => {
const monsters = judgeSelf(action.payload, state)
? state.meMonsters
: state.opMonsters;
clearIdleInteractivities(monsters);
};
// 增加怪兽
export const fetchMonsterMeta = createAsyncMetaThunk("duel/fetchMonsterMeta");
// 增加怪兽的超量素材
export const fetchOverlayMeta = createAsyncThunk(
"duel/fetchOverlayMeta",
async (param: {
controler: number;
sequence: number;
overlayCodes: number[];
append?: boolean;
}) => {
const controler = param.controler;
const sequence = param.sequence;
const overlayCodes = param.overlayCodes;
const metas = await Promise.all(
overlayCodes.map(async (id) => {
if (id == 0) {
return { id, data: {}, text: {} };
} else {
return await fetchCard(id, true);
}
})
);
const response = { controler, sequence, metas };
return response;
}
);
export const monsterCase = (builder: ActionReducerMapBuilder<DuelState>) => {
builder.addCase(fetchMonsterMeta.pending, (state, action) => {
// Meta结果没返回之前先更新`ID`
const controler = action.meta.arg.controler;
const sequence = action.meta.arg.sequence;
const position = action.meta.arg.position;
const code = action.meta.arg.code;
const meta = { id: code, data: {}, text: {} };
if (judgeSelf(controler, state)) {
extendOccupant(state.meMonsters, meta, sequence, position);
} else {
extendOccupant(state.opMonsters, meta, sequence, position);
}
});
builder.addCase(fetchMonsterMeta.fulfilled, (state, action) => {
const controler = action.payload.controler;
const sequence = action.payload.sequence;
const meta = action.payload.meta;
if (judgeSelf(controler, state)) {
extendOccupant(state.meMonsters, meta, sequence);
} else {
extendOccupant(state.opMonsters, meta, sequence);
}
});
builder.addCase(fetchOverlayMeta.pending, (state, action) => {
// Meta结果没返回之前先更新`ID`
const controler = action.meta.arg.controler;
const sequence = action.meta.arg.sequence;
const overlayCodes = action.meta.arg.overlayCodes;
const append = action.meta.arg.append;
const metas = overlayCodes.map((id) => {
return { id, data: {}, text: {} };
});
const monsters = judgeSelf(controler, state)
? state.meMonsters
: state.opMonsters;
if (monsters) {
const target = monsters.inner.find((_, idx) => idx == sequence);
if (target && target.occupant) {
if (append) {
target.overlay_materials = (target.overlay_materials || []).concat(
metas
);
} else {
target.overlay_materials = metas;
}
}
}
});
builder.addCase(fetchOverlayMeta.fulfilled, (state, action) => {
const controler = action.payload.controler;
const sequence = action.payload.sequence;
const overlayMetas = action.payload.metas;
const monsters = judgeSelf(controler, state)
? state.meMonsters
: state.opMonsters;
if (monsters) {
const target = monsters.inner.find((_, idx) => idx == sequence);
for (const meta of overlayMetas) {
for (const overlay of target?.overlay_materials || []) {
if (meta.id == overlay.id) {
overlay.data = meta.data;
overlay.text = meta.text;
}
}
}
}
});
};
// 删除怪兽
export const removeMonsterImpl: CaseReducer<
DuelState,
PayloadAction<{ controler: number; sequence: number }>
> = (state, action) => {
const controler = action.payload.controler;
const monsters = judgeSelf(controler, state)
? state.meMonsters
: state.opMonsters;
removeOccupant(monsters, action.payload.sequence);
removeOverlay(monsters, action.payload.sequence);
};
// 删除超量素材
export const removeOverlayImpl: CaseReducer<
DuelState,
PayloadAction<{
controler: number;
sequence: number;
overlaySequence: number;
}>
> = (state, action) => {
const controler = action.payload.controler;
const sequence = action.payload.sequence;
const overlaySequence = action.payload.overlaySequence;
const monsters = judgeSelf(controler, state)
? state.meMonsters
: state.opMonsters;
if (monsters) {
const target = monsters.inner.find((_, idx) => idx == sequence);
if (target && target.overlay_materials) {
target.overlay_materials = target.overlay_materials.filter(
(_, idx) => idx != overlaySequence
);
}
}
};
// 改变怪兽表示形式
export const setMonsterPositionImpl: CaseReducer<
DuelState,
PayloadAction<{
controler: number;
sequence: number;
position: ygopro.CardPosition;
}>
> = (state, action) => {
const controler = action.payload.controler;
const sequence = action.payload.sequence;
const position = action.payload.position;
const monsters = judgeSelf(controler, state)
? state.meMonsters
: state.opMonsters;
setPosition(monsters, sequence, position);
};
export const selectMeMonsters = (state: RootState) =>
state.duel.meMonsters || { inner: [] };
export const selectOpMonsters = (state: RootState) =>
state.duel.opMonsters || { inner: [] };
import { CaseReducer, PayloadAction } from "@reduxjs/toolkit";
import { RootState } from "@/store";
import { DuelState } from "./mod";
export interface PhaseState {
currentPhase: string; // 当前的阶段
enableBp: boolean; // 允许进入战斗阶段
enableM2: boolean; // 允许进入M2阶段
enableEp: boolean; // 允许回合结束
}
export const newPhaseImpl: CaseReducer<DuelState, PayloadAction<string>> = (
state,
action
) => {
if (state.phase) {
state.phase.currentPhase = action.payload;
} else {
state.phase = {
currentPhase: action.payload,
enableBp: false,
enableM2: false,
enableEp: false,
};
}
};
export const setEnableBpImpl: CaseReducer<DuelState, PayloadAction<boolean>> = (
state,
action
) => {
if (state.phase) {
state.phase.enableBp = action.payload;
}
};
export const setEnableM2Impl: CaseReducer<DuelState, PayloadAction<boolean>> = (
state,
action
) => {
if (state.phase) {
state.phase.enableM2 = action.payload;
}
};
export const setEnableEpImpl: CaseReducer<DuelState, PayloadAction<boolean>> = (
state,
action
) => {
if (state.phase) {
state.phase.enableEp = action.payload;
}
};
export const selectCurrentPhase = (state: RootState) =>
state.duel.phase?.currentPhase;
export const selectEnableBp = (state: RootState) =>
state.duel.phase?.enableBp || false;
export const selectEnableM2 = (state: RootState) =>
state.duel.phase?.enableBp || false;
export const selectEnableEp = (state: RootState) =>
state.duel.phase?.enableEp || false;
import { CaseReducer, PayloadAction } from "@reduxjs/toolkit";
import { DuelState } from "./mod";
import { judgeSelf } from "./util";
export interface TimeLimit {
leftTime: number;
}
// 更新计时
export const updateTimeLimitImpl: CaseReducer<
DuelState,
PayloadAction<[number, number]>
> = (state, action) => {
const player = action.payload[0];
const leftTime = action.payload[1];
if (judgeSelf(player, state)) {
state.meTimeLimit = { leftTime };
} else {
state.opTimeLimit = { leftTime };
}
};
import { CaseReducer, PayloadAction } from "@reduxjs/toolkit";
import { RootState } from "@/store";
import { DuelState } from "./mod";
import { judgeSelf } from "./util";
export const newTurnImpl: CaseReducer<DuelState, PayloadAction<number>> = (
state,
action
) => {
state.currentPlayer = action.payload;
};
export const selectCurrentPlayerIsMe = (state: RootState) =>
judgeSelf(state.duel.currentPlayer!, state.duel);
/*
* 对局内状态更新逻辑的一些共用函数和数据结构
*
* */
import { Draft } from "@reduxjs/toolkit";
import { ygopro } from "@/api";
import { CardState } from "./generic";
import { DuelState } from "./mod";
type Location =
| ygopro.CardLocation
| ReturnType<typeof ygopro.CardLocation.prototype.toObject>;
/*
* 通过`player`和`selfType`判断是应该处理自己还是对手
* */
export function judgeSelf(player: number, state: Draft<DuelState>): boolean {
const selfType = state.selfType;
if (selfType === 1) {
// 自己是先攻
return player == 0;
} else if (selfType === 2) {
// 自己是后攻
return player == 1;
} else {
// currently never reach
return false;
}
}
/*
* 通过`controler`,`zone`和`sequence`获取卡牌状态*/
export function findCardByLocation(
state: Draft<DuelState>,
location: Location
): CardState | undefined {
const controler = location.controler!;
const zone = location.location;
const sequence = location.sequence;
const finder = (_: any, idx: number) => idx == sequence;
switch (zone) {
case ygopro.CardZone.HAND: {
const hands = judgeSelf(controler, state) ? state.meHands : state.opHands;
return hands?.inner.find(finder);
}
case ygopro.CardZone.MZONE: {
const monsters = judgeSelf(controler, state)
? state.meMonsters
: state.opMonsters;
return monsters?.inner.find(finder);
}
case ygopro.CardZone.SZONE: {
const magics = judgeSelf(controler, state)
? state.meMagics
: state.opMagics;
return magics?.inner.find(finder);
}
case ygopro.CardZone.REMOVED: {
const banishedZones = judgeSelf(controler, state)
? state.meBanishedZone
: state.opBanishedZone;
return banishedZones?.inner.find(finder);
}
case ygopro.CardZone.GRAVE: {
const cemerety = judgeSelf(controler, state)
? state.meGraveyard
: state.opGraveyard;
return cemerety?.inner.find(finder);
}
default: {
return undefined;
}
}
}
export function cmpCardLocation(
left: Location,
right?: Location,
strict?: boolean
): boolean {
if (strict) {
return JSON.stringify(left) === JSON.stringify(right);
} else {
return (
left.controler === right?.controler &&
left.location === right?.location &&
left.sequence === right?.sequence
);
}
}
/*
* 加入房间状态更新逻辑
*
* */
import { createSlice } from "@reduxjs/toolkit";
import { RootState } from "@/store";
export interface JoinState {
value: boolean;
}
const initialState: JoinState = {
value: false,
};
const joinedSlice = createSlice({
name: "join",
initialState,
reducers: {
setJoined: (state) => {
state.value = true;
},
setUnJoined: (state) => {
state.value = false;
},
},
});
export const { setJoined, setUnJoined } = joinedSlice.actions;
export const selectJoined = (state: RootState) => state.join.value;
export default joinedSlice.reducer;
/*
* 猜拳页面的状态更新逻辑
*
* */
import { createSlice } from "@reduxjs/toolkit";
import { RootState } from "@/store";
export interface moraState {
duelStart: boolean;
selectHandAble: boolean;
selectTpAble: boolean;
}
const initialState: moraState = {
duelStart: false,
selectHandAble: false,
selectTpAble: false,
};
const moraSlice = createSlice({
name: "mora",
initialState,
reducers: {
duelStart: (state) => {
state.duelStart = true;
},
selectHandAble: (state) => {
state.selectHandAble = true;
},
unSelectHandAble: (state) => {
state.selectHandAble = false;
},
selectTpAble: (state) => {
state.selectTpAble = true;
},
unSelectTpAble: (state) => {
state.selectTpAble = false;
},
},
});
export const {
duelStart,
selectHandAble,
unSelectHandAble,
selectTpAble,
unSelectTpAble,
} = moraSlice.actions;
export const selectDuelStart = (state: RootState) => state.mora.duelStart;
export const selectHandSelectAble = (state: RootState) =>
state.mora.selectHandAble;
export const selectTpSelectAble = (state: RootState) => state.mora.selectTpAble;
export default moraSlice.reducer;
/*
* 进入房间的玩家状态更新逻辑
*
* */
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { RootState } from "@/store";
export interface Player {
name?: string;
state?: string;
isHost?: boolean;
deckInfo?: deckInfo;
}
export interface deckInfo {
mainCnt: number;
extraCnt: number;
sideCnt: number;
}
export interface playerState {
player0: Player;
player1: Player;
observerCount: number;
isHost: boolean;
}
const initialState: playerState = {
player0: {},
player1: {},
observerCount: 0,
isHost: false,
};
const playerSlice = createSlice({
name: "player",
initialState,
reducers: {
player0Enter: (state, action: PayloadAction<string>) => {
state.player0.name = action.payload;
},
player1Enter: (state, action: PayloadAction<string>) => {
state.player1.name = action.payload;
},
player0Update: (state, action: PayloadAction<string>) => {
state.player0.state = action.payload;
},
player1Update: (state, action: PayloadAction<string>) => {
state.player1.state = action.payload;
},
player0Leave: (state) => {
state.player0 = {};
},
player1Leave: (state) => {
state.player1 = {};
},
player0DeckInfo: (state, action: PayloadAction<deckInfo>) => {
state.player0.deckInfo = action.payload;
},
player1DeckInfo: (state, action: PayloadAction<deckInfo>) => {
state.player1.deckInfo = action.payload;
},
hostChange: (state, action: PayloadAction<number>) => {
const i = action.payload;
if (i === 0) {
state.player0.isHost = true;
state.player1.isHost = false;
} else {
state.player1.isHost = true;
state.player0.isHost = false;
}
},
observerIncrement: (state) => {
state.observerCount += 1;
},
observerChange: (state, action: PayloadAction<number>) => {
state.observerCount = action.payload;
},
updateIsHost: (state, action: PayloadAction<boolean>) => {
state.isHost = action.payload;
},
},
});
export const {
player0Enter,
player1Enter,
player0Update,
player1Update,
player0Leave,
player1Leave,
player0DeckInfo,
player1DeckInfo,
hostChange,
observerIncrement,
observerChange,
updateIsHost,
} = playerSlice.actions;
export const selectPlayer0 = (state: RootState) => state.player.player0;
export const selectPlayer1 = (state: RootState) => state.player.player1;
export const selectIsHost = (state: RootState) => state.player.isHost;
export const selectObserverCount = (state: RootState) =>
state.player.observerCount;
export default playerSlice.reducer;
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/stores";
import { AppDispatch } from "@/store";
import { fetchEsHintMeta as FIXME_fetchEsHintMeta } from "@/valtioStores";
export default ( export default (attack: ygopro.StocGameMessage.MsgAttack) => {
attack: ygopro.StocGameMessage.MsgAttack, fetchEsHintMeta({
dispatch: AppDispatch
) => {
// dispatch(
// fetchEsHintMeta({ originMsg: "「[?]」攻击时", location: attack.location })
// );
FIXME_fetchEsHintMeta({
originMsg: "「[?]」攻击时", originMsg: "「[?]」攻击时",
location: attack.location, location: attack.location,
}); });
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/stores";
import { AppDispatch } from "@/store";
import {
fetchEsHintMeta as FIXME_fetchEsHintMeta,
matStore,
} from "@/valtioStores";
export default ( export default (_: ygopro.StocGameMessage.MsgAttackDisabled) => {
_: ygopro.StocGameMessage.MsgAttackDisabled, fetchEsHintMeta({ originMsg: "攻击被无效时" });
dispatch: AppDispatch
) => {
// dispatch(fetchEsHintMeta({ originMsg: "攻击被无效时" }));
FIXME_fetchEsHintMeta({ originMsg: "攻击被无效时" });
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/stores";
import { AppDispatch } from "@/store"; export default (chaining: ygopro.StocGameMessage.MsgChaining) => {
import { fetchEsHintMeta({
fetchEsHintMeta as FIXME_fetchEsHintMeta,
matStore,
} from "@/valtioStores";
export default (
chaining: ygopro.StocGameMessage.MsgChaining,
dispatch: AppDispatch
) => {
// dispatch(
// fetchEsHintMeta({ originMsg: "「[?]」被发动时", cardID: chaining.code })
// );
FIXME_fetchEsHintMeta({
originMsg: "「[?]」被发动时", originMsg: "「[?]」被发动时",
cardID: chaining.code, cardID: chaining.code,
}); });
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { fetchHandsMeta } from "@/reducers/duel/handsSlice"; import { fetchEsHintMeta, matStore } from "@/stores";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice";
import { AppDispatch } from "@/store";
import {
fetchEsHintMeta as FIXME_fetchEsHintMeta,
matStore,
} from "@/valtioStores";
export default ( export default (draw: ygopro.StocGameMessage.MsgDraw) => {
draw: ygopro.StocGameMessage.MsgDraw, fetchEsHintMeta({ originMsg: "玩家抽卡时" });
dispatch: AppDispatch
) => {
// dispatch(fetchEsHintMeta({ originMsg: "玩家抽卡时" }));
// dispatch(fetchHandsMeta({ controler: draw.player, codes: draw.cards }));
FIXME_fetchEsHintMeta({ originMsg: "玩家抽卡时" });
matStore.hands.of(draw.player).add(draw.cards); matStore.hands.of(draw.player).add(draw.cards);
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/stores";
import { AppDispatch } from "@/store";
import { fetchEsHintMeta as FIXME_fetchEsHintMeta } from "@/valtioStores";
export default ( export default (_: ygopro.StocGameMessage.MsgFlipSummoned) => {
_: ygopro.StocGameMessage.MsgFlipSummoned, fetchEsHintMeta({ originMsg: 1608 });
dispatch: AppDispatch
) => {
// dispatch(fetchEsHintMeta({ originMsg: 1608 }));
FIXME_fetchEsHintMeta({ originMsg: 1608 });
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/stores";
import { AppDispatch } from "@/store";
import { fetchEsHintMeta as FIXME_fetchEsHintMeta } from "@/valtioStores";
export default ( export default (flipSummoning: ygopro.StocGameMessage.MsgFlipSummoning) => {
flipSummoning: ygopro.StocGameMessage.MsgFlipSummoning, fetchEsHintMeta({
dispatch: AppDispatch
) => {
// dispatch(
// fetchEsHintMeta({
// originMsg: "「[?]」反转召唤宣言时",
// cardID: flipSummoning.code,
// })
// );
FIXME_fetchEsHintMeta({
originMsg: "「[?]」反转召唤宣言时", originMsg: "「[?]」反转召唤宣言时",
cardID: flipSummoning.code, cardID: flipSummoning.code,
}); });
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { setWaiting } from "@/reducers/duel/mod"; import { matStore } from "@/stores";
import { store } from "@/store";
import { matStore } from "@/valtioStores";
import onMsgAttack from "./attack"; import onMsgAttack from "./attack";
import onMsgAttackDisable from "./attackDisable"; import onMsgAttackDisable from "./attackDisable";
...@@ -58,212 +56,210 @@ const ActiveList = [ ...@@ -58,212 +56,210 @@ const ActiveList = [
]; ];
export default function handleGameMsg(pb: ygopro.YgoStocMsg) { export default function handleGameMsg(pb: ygopro.YgoStocMsg) {
const dispatch = store.dispatch;
const msg = pb.stoc_game_msg; const msg = pb.stoc_game_msg;
if (ActiveList.includes(msg.gameMsg)) { if (ActiveList.includes(msg.gameMsg)) {
dispatch(setWaiting(false));
matStore.waiting = false; matStore.waiting = false;
} }
switch (msg.gameMsg) { switch (msg.gameMsg) {
case "start": { case "start": {
onMsgStart(msg.start, dispatch); onMsgStart(msg.start);
break; break;
} }
case "draw": { case "draw": {
onMsgDraw(msg.draw, dispatch); onMsgDraw(msg.draw);
break; break;
} }
case "new_turn": { case "new_turn": {
onMsgNewTurn(msg.new_turn, dispatch); onMsgNewTurn(msg.new_turn);
break; break;
} }
case "new_phase": { case "new_phase": {
onMsgNewPhase(msg.new_phase, dispatch); onMsgNewPhase(msg.new_phase);
break; break;
} }
case "hint": { case "hint": {
onMsgHint(msg.hint, dispatch); onMsgHint(msg.hint);
break; break;
} }
case "select_idle_cmd": { case "select_idle_cmd": {
onMsgSelectIdleCmd(msg.select_idle_cmd, dispatch); onMsgSelectIdleCmd(msg.select_idle_cmd);
break; break;
} }
case "select_place": { case "select_place": {
onMsgSelectPlace(msg.select_place, dispatch); onMsgSelectPlace(msg.select_place);
break; break;
} }
case "move": { case "move": {
onMsgMove(msg.move, dispatch); onMsgMove(msg.move);
break; break;
} }
case "select_card": { case "select_card": {
onMsgSelectCard(msg.select_card, dispatch); onMsgSelectCard(msg.select_card);
break; break;
} }
case "select_chain": { case "select_chain": {
onMsgSelectChain(msg.select_chain, dispatch); onMsgSelectChain(msg.select_chain);
break; break;
} }
case "select_effect_yn": { case "select_effect_yn": {
onMsgSelectEffectYn(msg.select_effect_yn, dispatch); onMsgSelectEffectYn(msg.select_effect_yn);
break; break;
} }
case "select_position": { case "select_position": {
onMsgSelectPosition(msg.select_position, dispatch); onMsgSelectPosition(msg.select_position);
break; break;
} }
case "select_option": { case "select_option": {
onMsgSelectOption(msg.select_option, dispatch); onMsgSelectOption(msg.select_option);
break; break;
} }
case "shuffle_hand": { case "shuffle_hand": {
onMsgShuffleHand(msg.shuffle_hand, dispatch); onMsgShuffleHand(msg.shuffle_hand);
break; break;
} }
case "select_battle_cmd": { case "select_battle_cmd": {
onMsgSelectBattleCmd(msg.select_battle_cmd, dispatch); onMsgSelectBattleCmd(msg.select_battle_cmd);
break; break;
} }
case "pos_change": { case "pos_change": {
onMsgPosChange(msg.pos_change, dispatch); onMsgPosChange(msg.pos_change);
break; break;
} }
case "select_unselect_card": { case "select_unselect_card": {
onMsgSelectUnselectCard(msg.select_unselect_card, dispatch); onMsgSelectUnselectCard(msg.select_unselect_card);
break; break;
} }
case "select_yes_no": { case "select_yes_no": {
onMsgSelectYesNo(msg.select_yes_no, dispatch); onMsgSelectYesNo(msg.select_yes_no);
break; break;
} }
case "update_hp": { case "update_hp": {
onMsgUpdateHp(msg.update_hp, dispatch); onMsgUpdateHp(msg.update_hp);
break; break;
} }
case "win": { case "win": {
onMsgWin(msg.win, dispatch); onMsgWin(msg.win);
break; break;
} }
case "wait": { case "wait": {
onMsgWait(msg.wait, dispatch); onMsgWait(msg.wait);
break; break;
} }
case "update_data": { case "update_data": {
onMsgUpdateData(msg.update_data, dispatch); onMsgUpdateData(msg.update_data);
break; break;
} }
case "reload_field": { case "reload_field": {
onMsgReloadField(msg.reload_field, dispatch); onMsgReloadField(msg.reload_field);
break; break;
} }
case "select_sum": { case "select_sum": {
onMsgSelectSum(msg.select_sum, dispatch); onMsgSelectSum(msg.select_sum);
break; break;
} }
case "select_tribute": { case "select_tribute": {
onMsgSelectTribute(msg.select_tribute, dispatch); onMsgSelectTribute(msg.select_tribute);
break; break;
} }
case "update_counter": { case "update_counter": {
onMsgUpdateCounter(msg.update_counter, dispatch); onMsgUpdateCounter(msg.update_counter);
break; break;
} }
case "select_counter": { case "select_counter": {
onMsgSelectCounter(msg.select_counter, dispatch); onMsgSelectCounter(msg.select_counter);
break; break;
} }
case "sort_card": { case "sort_card": {
onMsgSortCard(msg.sort_card, dispatch); onMsgSortCard(msg.sort_card);
break; break;
} }
case "set": { case "set": {
onMsgSet(msg.set, dispatch); onMsgSet(msg.set);
break; break;
} }
case "swap": { case "swap": {
onMsgSwap(msg.swap, dispatch); onMsgSwap(msg.swap);
break; break;
} }
case "attack": { case "attack": {
onMsgAttack(msg.attack, dispatch); onMsgAttack(msg.attack);
break; break;
} }
case "attack_disable": { case "attack_disable": {
onMsgAttackDisable(msg.attack_disable, dispatch); onMsgAttackDisable(msg.attack_disable);
break; break;
} }
case "chaining": { case "chaining": {
onMsgChaining(msg.chaining, dispatch); onMsgChaining(msg.chaining);
break; break;
} }
case "summoning": { case "summoning": {
onMsgSummoning(msg.summoning, dispatch); onMsgSummoning(msg.summoning);
break; break;
} }
case "summoned": { case "summoned": {
onMsgSummoned(msg.summoned, dispatch); onMsgSummoned(msg.summoned);
break; break;
} }
case "flip_summoning": { case "flip_summoning": {
onMsgFlipSummoning(msg.flip_summoning, dispatch); onMsgFlipSummoning(msg.flip_summoning);
break; break;
} }
case "flip_summoned": { case "flip_summoned": {
onMsgFilpSummoned(msg.flip_summoned, dispatch); onMsgFilpSummoned(msg.flip_summoned);
break; break;
} }
case "sp_summoning": { case "sp_summoning": {
onMsgSpSummoning(msg.sp_summoning, dispatch); onMsgSpSummoning(msg.sp_summoning);
break; break;
} }
case "sp_summoned": { case "sp_summoned": {
onMsgSpSummoned(msg.sp_summoned, dispatch); onMsgSpSummoned(msg.sp_summoned);
break; break;
} }
case "unimplemented": { case "unimplemented": {
onUnimplemented(msg.unimplemented, dispatch); onUnimplemented(msg.unimplemented);
break; break;
} }
......
...@@ -3,33 +3,22 @@ import { ...@@ -3,33 +3,22 @@ import {
fetchCommonHintMeta, fetchCommonHintMeta,
fetchEsHintMeta, fetchEsHintMeta,
fetchSelectHintMeta, fetchSelectHintMeta,
} from "@/reducers/duel/hintSlice"; } from "@/stores";
import { AppDispatch } from "@/store";
import {
fetchCommonHintMeta as FIXME_fetchCommonHintMeta,
fetchEsHintMeta as FIXME_fetchEsHintMeta,
fetchSelectHintMeta as FIXME_fetchSelectHintMeta,
} from "@/valtioStores";
import MsgHint = ygopro.StocGameMessage.MsgHint; import MsgHint = ygopro.StocGameMessage.MsgHint;
export default (hint: MsgHint, dispatch: AppDispatch) => { export default (hint: MsgHint) => {
switch (hint.hint_type) { switch (hint.hint_type) {
case MsgHint.HintType.HINT_EVENT: { case MsgHint.HintType.HINT_EVENT: {
// dispatch(fetchEsHintMeta({ originMsg: hint.hint_data })); fetchEsHintMeta({ originMsg: hint.hint_data });
FIXME_fetchEsHintMeta({ originMsg: hint.hint_data });
break; break;
} }
case MsgHint.HintType.HINT_MESSAGE: { case MsgHint.HintType.HINT_MESSAGE: {
// dispatch(fetchCommonHintMeta(hint.hint_data)); fetchCommonHintMeta(hint.hint_data);
FIXME_fetchCommonHintMeta(hint.hint_data);
break; break;
} }
case MsgHint.HintType.HINT_SELECTMSG: { case MsgHint.HintType.HINT_SELECTMSG: {
// dispatch( fetchSelectHintMeta({
// fetchSelectHintMeta({ selectHintData: hint.hint_data, esHint: "" })
// );
FIXME_fetchSelectHintMeta({
selectHintData: hint.hint_data, selectHintData: hint.hint_data,
esHint: "", esHint: "",
}); });
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import MsgMove = ygopro.StocGameMessage.MsgMove; import { fetchOverlayMeta, store } from "@/stores";
import { fetchBanishedZoneMeta } from "@/reducers/duel/banishedZoneSlice"; type MsgMove = ygopro.StocGameMessage.MsgMove;
import { fetchExtraDeckMeta } from "@/reducers/duel/extraDeckSlice";
import { fetchGraveyardMeta } from "@/reducers/duel/graveyardSlice";
import { insertHandMeta } from "@/reducers/duel/handsSlice";
import { fetchMagicMeta } from "@/reducers/duel/magicSlice";
import {
removeBanishedZone,
removeExtraDeck,
removeGraveyard,
removeHand,
removeMagic,
removeMonster,
removeOverlay,
} from "@/reducers/duel/mod";
import {
fetchMonsterMeta,
fetchOverlayMeta,
} from "@/reducers/duel/monstersSlice";
import { AppDispatch } from "@/store";
import {
fetchOverlayMeta as FIXME_fetchOverlayMeta,
valtioStore,
} from "@/valtioStores";
import { REASON_MATERIAL } from "../../common"; import { REASON_MATERIAL } from "../../common";
const { matStore } = valtioStore; const { matStore } = store;
const OVERLAY_STACK: { code: number; sequence: number }[] = []; const OVERLAY_STACK: { code: number; sequence: number }[] = [];
export default (move: MsgMove, dispatch: AppDispatch) => { export default (move: MsgMove) => {
const code = move.code; const code = move.code;
const from = move.from; const from = move.from;
const to = move.to; const to = move.to;
...@@ -80,7 +58,7 @@ export default (move: MsgMove, dispatch: AppDispatch) => { ...@@ -80,7 +58,7 @@ export default (move: MsgMove, dispatch: AppDispatch) => {
const sorted = overlayMetarials const sorted = overlayMetarials
.sort((a, b) => a.sequence - b.sequence) .sort((a, b) => a.sequence - b.sequence)
.map((overlay) => overlay.code); .map((overlay) => overlay.code);
FIXME_fetchOverlayMeta(to.controler, to.sequence, sorted); fetchOverlayMeta(to.controler, to.sequence, sorted);
// 设置Occupant,和魔陷区/其他区共用一个逻辑,特地不写break // 设置Occupant,和魔陷区/其他区共用一个逻辑,特地不写break
} }
case ygopro.CardZone.SZONE: { case ygopro.CardZone.SZONE: {
...@@ -104,7 +82,7 @@ export default (move: MsgMove, dispatch: AppDispatch) => { ...@@ -104,7 +82,7 @@ export default (move: MsgMove, dispatch: AppDispatch) => {
OVERLAY_STACK.push({ code, sequence: to.overlay_sequence }); OVERLAY_STACK.push({ code, sequence: to.overlay_sequence });
} else { } else {
// 其他情况下,比如“宵星的机神 丁吉尔苏”的“补充超量素材”效果,直接更新状态中 // 其他情况下,比如“宵星的机神 丁吉尔苏”的“补充超量素材”效果,直接更新状态中
FIXME_fetchOverlayMeta(to.controler, to.sequence, [code], true); fetchOverlayMeta(to.controler, to.sequence, [code], true);
} }
break; break;
} }
...@@ -113,163 +91,4 @@ export default (move: MsgMove, dispatch: AppDispatch) => { ...@@ -113,163 +91,4 @@ export default (move: MsgMove, dispatch: AppDispatch) => {
break; break;
} }
} }
// switch (from.location) {
// case ygopro.CardZone.HAND: {
// dispatch(removeHand([from.controler, from.sequence]));
// break;
// }
// case ygopro.CardZone.MZONE: {
// dispatch(
// removeMonster({ controler: from.controler, sequence: from.sequence })
// );
// break;
// }
// case ygopro.CardZone.SZONE: {
// dispatch(
// removeMagic({ controler: from.controler, sequence: from.sequence })
// );
// break;
// }
// case ygopro.CardZone.GRAVE: {
// dispatch(
// removeGraveyard({ controler: from.controler, sequence: from.sequence })
// );
// break;
// }
// case ygopro.CardZone.REMOVED: {
// dispatch(
// removeBanishedZone({
// controler: from.controler,
// sequence: from.sequence,
// })
// );
// break;
// }
// case ygopro.CardZone.EXTRA: {
// dispatch(
// removeExtraDeck({ controler: from.controler, sequence: from.sequence })
// );
// break;
// }
// case ygopro.CardZone.OVERLAY: {
// dispatch(
// removeOverlay({
// controler: from.controler,
// sequence: from.sequence,
// overlaySequence: from.overlay_sequence,
// })
// );
// break;
// }
// default: {
// console.log(`Unhandled zone type ${from.location}`);
// break;
// }
// }
// switch (to.location) {
// case ygopro.CardZone.MZONE: {
// dispatch(
// fetchMonsterMeta({
// controler: to.controler,
// sequence: to.sequence,
// position: to.position,
// code,
// })
// );
// // 处理超量素材
// const overlayMetarials = OVERLAY_STACK.splice(0, OVERLAY_STACK.length);
// let sorted = overlayMetarials
// .sort((a, b) => a.sequence - b.sequence)
// .map((overlay) => overlay.code);
// dispatch(
// fetchOverlayMeta({
// controler: to.controler,
// sequence: to.sequence,
// overlayCodes: sorted,
// })
// );
// break;
// }
// case ygopro.CardZone.SZONE: {
// dispatch(
// fetchMagicMeta({
// controler: to.controler,
// sequence: to.sequence,
// position: to.position,
// code,
// })
// );
// break;
// }
// case ygopro.CardZone.GRAVE: {
// dispatch(
// fetchGraveyardMeta({
// controler: to.controler,
// sequence: to.sequence,
// code,
// })
// );
// break;
// }
// case ygopro.CardZone.HAND: {
// dispatch(
// insertHandMeta({ controler: to.controler, sequence: to.sequence, code })
// );
// break;
// }
// case ygopro.CardZone.REMOVED: {
// dispatch(
// fetchBanishedZoneMeta({
// controler: to.controler,
// sequence: to.sequence,
// code,
// })
// );
// break;
// }
// case ygopro.CardZone.EXTRA: {
// dispatch(
// fetchExtraDeckMeta({
// controler: to.controler,
// sequence: to.sequence,
// code,
// })
// );
// break;
// }
// case ygopro.CardZone.OVERLAY: {
// if (reason == REASON_MATERIAL) {
// // 超量素材在进行超量召唤时,若玩家未选择超量怪兽的位置,会“沉到决斗盘下面”,`reason`字段值是`REASON_MATERIAL`
// // 这时候将它们放到一个栈中,待超量怪兽的Move消息到来时从栈中获取超量素材补充到状态中
// OVERLAY_STACK.push({ code, sequence: to.overlay_sequence });
// } else {
// // 其他情况下,比如“宵星的机神 丁吉尔苏”的“补充超量素材”效果,直接更新状态中
// dispatch(
// fetchOverlayMeta({
// controler: to.controler,
// sequence: to.sequence,
// overlayCodes: [code],
// append: true,
// })
// );
// }
// break;
// }
// default: {
// console.log(`Unhandled zone type ${to.location}`);
// break;
// }
// }
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { updatePhase } from "@/reducers/duel/mod"; import { matStore, type PhaseName } from "@/stores";
import { AppDispatch } from "@/store";
import { matStore, type PhaseName } from "@/valtioStores";
export default (
newPhase: ygopro.StocGameMessage.MsgNewPhase,
dispatch: AppDispatch
) => {
// dispatch(
// updatePhase(
// ygopro.StocGameMessage.MsgNewPhase.PhaseType[newPhase.phase_type]
// )
// );
export default (newPhase: ygopro.StocGameMessage.MsgNewPhase) => {
// ts本身还没有这么智能,所以需要手动指定类型 // ts本身还没有这么智能,所以需要手动指定类型
const currentPhase = ygopro.StocGameMessage.MsgNewPhase.PhaseType[ const currentPhase = ygopro.StocGameMessage.MsgNewPhase.PhaseType[
newPhase.phase_type newPhase.phase_type
] as PhaseName; ] as PhaseName;
matStore.phase.currentPhase = currentPhase; matStore.phase.currentPhase = currentPhase;
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { updateTurn } from "@/reducers/duel/mod"; import { matStore } from "@/stores";
import { AppDispatch } from "@/store";
import { matStore } from "@/valtioStores";
export default ( export default (newTurn: ygopro.StocGameMessage.MsgNewTurn) => {
newTurn: ygopro.StocGameMessage.MsgNewTurn,
dispatch: AppDispatch
) => {
const player = newTurn.player; const player = newTurn.player;
// dispatch(updateTurn(player));
matStore.currentPlayer = player; matStore.currentPlayer = player;
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice";
import { setMagicPosition, setMonsterPosition } from "@/reducers/duel/mod";
import { AppDispatch } from "@/store";
import MsgPosChange = ygopro.StocGameMessage.MsgPosChange; import MsgPosChange = ygopro.StocGameMessage.MsgPosChange;
import { import { fetchEsHintMeta, matStore } from "@/stores";
fetchEsHintMeta as FIXME_fetchEsHintMeta, export default (posChange: MsgPosChange) => {
matStore,
} from "@/valtioStores";
export default (posChange: MsgPosChange, dispatch: AppDispatch) => {
const { location, controler, sequence } = posChange.card_info; const { location, controler, sequence } = posChange.card_info;
switch (location) { switch (location) {
case ygopro.CardZone.MZONE: { case ygopro.CardZone.MZONE: {
// dispatch(
// setMonsterPosition({
// controler: controler,
// sequence,
// position: posChange.cur_position,
// })
// );
matStore.monsters.of(controler)[sequence].location.position = matStore.monsters.of(controler)[sequence].location.position =
posChange.cur_position; posChange.cur_position;
break; break;
} }
case ygopro.CardZone.SZONE: { case ygopro.CardZone.SZONE: {
// dispatch(
// setMagicPosition({
// controler: controler,
// sequence,
// position: posChange.cur_position,
// })
// );
matStore.magics.of(controler)[sequence].location.position = matStore.magics.of(controler)[sequence].location.position =
posChange.cur_position; posChange.cur_position;
...@@ -41,9 +21,7 @@ export default (posChange: MsgPosChange, dispatch: AppDispatch) => { ...@@ -41,9 +21,7 @@ export default (posChange: MsgPosChange, dispatch: AppDispatch) => {
console.log(`Unhandled zone ${location}`); console.log(`Unhandled zone ${location}`);
} }
} }
fetchEsHintMeta({
// dispatch(fetchEsHintMeta({ originMsg: 1600 }));
FIXME_fetchEsHintMeta({
originMsg: 1600, originMsg: 1600,
}); });
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { reloadField } from "@/reducers/duel/mod"; import { matStore } from "@/stores";
import { AppDispatch } from "@/store";
import { matStore } from "@/valtioStores";
type MsgReloadField = ygopro.StocGameMessage.MsgReloadField; type MsgReloadField = ygopro.StocGameMessage.MsgReloadField;
type ZoneActions = ygopro.StocGameMessage.MsgReloadField.ZoneAction[]; type ZoneActions = ygopro.StocGameMessage.MsgReloadField.ZoneAction[];
export default (field: MsgReloadField, dispatch: AppDispatch) => { export default (field: MsgReloadField) => {
// dispatch(reloadField(field)); const _duel_rule = field.duel_rule; // TODO: duel_rule
const _duel_rule = field.duel_rule;
const gamers = ["me", "op"] as const; const gamers = ["me", "op"] as const;
gamers.forEach((gamer) => { gamers.forEach((gamer) => {
......
import { ActionCreatorWithPayload } from "@reduxjs/toolkit";
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { Interactivity, InteractType } from "@/reducers/duel/generic";
import {
addHandsIdleInteractivity,
addMagicIdleInteractivities,
addMonsterIdleInteractivities,
clearAllIdleInteractivities,
setEnableEp,
setEnableM2,
} from "@/reducers/duel/mod";
import { AppDispatch } from "@/store";
import { import {
clearAllIdleInteractivities as FIXME_clearAllIdleInteractivities, clearAllIdleInteractivities as clearAllIdleInteractivities,
type Interactivity,
InteractType,
matStore, matStore,
} from "@/valtioStores"; } from "@/stores";
import MsgSelectBattleCmd = ygopro.StocGameMessage.MsgSelectBattleCmd; import MsgSelectBattleCmd = ygopro.StocGameMessage.MsgSelectBattleCmd;
export default (selectBattleCmd: MsgSelectBattleCmd, dispatch: AppDispatch) => { export default (selectBattleCmd: MsgSelectBattleCmd) => {
const player = selectBattleCmd.player; const player = selectBattleCmd.player;
const cmds = selectBattleCmd.battle_cmds; const cmds = selectBattleCmd.battle_cmds;
// 先清掉之前的互动性 // 先清掉之前的互动性
// dispatch(clearAllIdleInteractivities(player)); clearAllIdleInteractivities(player);
FIXME_clearAllIdleInteractivities(player);
// const dispatcher = (
// battleData: MsgSelectBattleCmd.BattleCmd.BattleData,
// interactType: InteractType | undefined,
// actionCreator: ActionCreatorWithPayload<
// {
// player: number;
// sequence: number;
// interactivity: Interactivity<number>;
// },
// string
// >
// ) => {
// const cardInfo = battleData.card_info;
// if (interactType === InteractType.ACTIVATE) {
// dispatch(
// actionCreator({
// player,
// sequence: cardInfo.sequence,
// interactivity: {
// interactType,
// activateIndex: battleData.effect_description,
// response: battleData.response,
// },
// })
// );
// } else if (interactType === InteractType.ATTACK) {
// dispatch(
// actionCreator({
// player,
// sequence: cardInfo.sequence,
// interactivity: {
// interactType,
// directAttackAble: battleData.direct_attackable,
// response: battleData.response,
// },
// })
// );
// } else {
// console.log(`Unhandled InteractType`);
// }
// };
cmds.forEach((cmd) => { cmds.forEach((cmd) => {
const interactType = battleTypeToInteracType(cmd.battle_type); const interactType = battleTypeToInteracType(cmd.battle_type);
...@@ -83,7 +29,7 @@ export default (selectBattleCmd: MsgSelectBattleCmd, dispatch: AppDispatch) => { ...@@ -83,7 +29,7 @@ export default (selectBattleCmd: MsgSelectBattleCmd, dispatch: AppDispatch) => {
[InteractType.ACTIVATE]: { activateIndex: data.effect_description }, [InteractType.ACTIVATE]: { activateIndex: data.effect_description },
[InteractType.ATTACK]: { directAttackAble: data.direct_attackable }, [InteractType.ATTACK]: { directAttackAble: data.direct_attackable },
}; };
const tmp = map[interactType]; const tmp = map[interactType]; // 添加额外信息
matStore matStore
.in(location) .in(location)
.of(player) .of(player)
...@@ -95,34 +41,8 @@ export default (selectBattleCmd: MsgSelectBattleCmd, dispatch: AppDispatch) => { ...@@ -95,34 +41,8 @@ export default (selectBattleCmd: MsgSelectBattleCmd, dispatch: AppDispatch) => {
} else { } else {
console.warn(`Undefined InteractType`); console.warn(`Undefined InteractType`);
} }
// >>> 从这开始删除 >>>
// switch (location) {
// case ygopro.CardZone.HAND: {
// dispatcher(data, interactType, addHandsIdleInteractivity);
// break;
// }
// case ygopro.CardZone.MZONE: {
// dispatcher(data, interactType, addMonsterIdleInteractivities);
// break;
// }
// case ygopro.CardZone.SZONE: {
// dispatcher(data, interactType, addMagicIdleInteractivities);
// break;
// }
// default: {
// }
// }
// <<< 到这结束删除,上面的const dispatcher也删掉 <<<
}); });
}); });
// dispatch(setEnableM2(selectBattleCmd.enable_m2));
// dispatch(setEnableEp(selectBattleCmd.enable_ep));
matStore.phase.enableM2 = selectBattleCmd.enable_m2; matStore.phase.enableM2 = selectBattleCmd.enable_m2;
matStore.phase.enableEp = selectBattleCmd.enable_ep; matStore.phase.enableEp = selectBattleCmd.enable_ep;
}; };
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import {
setCheckCardModalIsOpen,
setCheckCardModalMinMax,
setCheckCardModalOnSubmit,
} from "@/reducers/duel/mod";
import { fetchCheckCardMeta } from "@/reducers/duel/modal/mod";
import { AppDispatch } from "@/store";
import MsgSelectCard = ygopro.StocGameMessage.MsgSelectCard; import MsgSelectCard = ygopro.StocGameMessage.MsgSelectCard;
import { import { fetchCheckCardMeta, messageStore } from "@/stores";
fetchCheckCardMeta as FIXME_fetchCheckCardMeta,
messageStore,
} from "@/valtioStores";
import { CardZoneToChinese } from "./util"; import { CardZoneToChinese } from "./util";
export default (selectCard: MsgSelectCard, dispatch: AppDispatch) => { export default (selectCard: MsgSelectCard) => {
const _player = selectCard.player; const _player = selectCard.player;
const _cancelable = selectCard.cancelable; // TODO: 处理可取消逻辑 const _cancelable = selectCard.cancelable; // TODO: 处理可取消逻辑
const min = selectCard.min; const min = selectCard.min;
...@@ -22,35 +12,17 @@ export default (selectCard: MsgSelectCard, dispatch: AppDispatch) => { ...@@ -22,35 +12,17 @@ export default (selectCard: MsgSelectCard, dispatch: AppDispatch) => {
const cards = selectCard.cards; const cards = selectCard.cards;
// TODO: handle release_param // TODO: handle release_param
// dispatch(setCheckCardModalMinMax({ min, max }));
// dispatch(setCheckCardModalOnSubmit("sendSelectCardResponse"));
messageStore.checkCardModal.selectMin = min; messageStore.checkCardModal.selectMin = min;
messageStore.checkCardModal.selectMax = max; messageStore.checkCardModal.selectMax = max;
messageStore.checkCardModal.onSubmit = "sendSelectCardResponse"; messageStore.checkCardModal.onSubmit = "sendSelectCardResponse";
for (const card of cards) { for (const card of cards) {
const tagName = CardZoneToChinese(card.location.location); const tagName = CardZoneToChinese(card.location.location);
// dispatch( fetchCheckCardMeta(card.location.location, {
// fetchCheckCardMeta({
// tagName,
// option: {
// code: card.code,
// location: card.location,
// response: card.response,
// },
// })
// );
// FIXME: rename
FIXME_fetchCheckCardMeta(card.location.location, {
code: card.code, code: card.code,
location: card.location, location: card.location,
response: card.response, response: card.response,
}); });
} }
// dispatch(setCheckCardModalIsOpen(true));
messageStore.checkCardModal.isOpen = true; messageStore.checkCardModal.isOpen = true;
}; };
import { ygopro } from "@/api"; import { sendSelectChainResponse, ygopro } from "@/api";
import { sendSelectChainResponse } from "@/api/ocgcore/ocgHelper";
import { fetchSelectHintMeta } from "@/reducers/duel/hintSlice";
import { import {
setCheckCardMOdalCancelAble, fetchCheckCardMeta,
setCheckCardModalCancelResponse, fetchSelectHintMeta,
setCheckCardModalIsOpen,
setCheckCardModalMinMax,
setCheckCardModalOnSubmit,
} from "@/reducers/duel/mod";
import { fetchCheckCardMeta } from "@/reducers/duel/modal/mod";
import { AppDispatch } from "@/store";
import {
fetchCheckCardMeta as FIXME_fetchCheckCardMeta,
fetchSelectHintMeta as FIXME_fetchSelectHintMeta,
messageStore, messageStore,
} from "@/valtioStores"; } from "@/stores";
import { CardZoneToChinese } from "./util";
type MsgSelectChain = ygopro.StocGameMessage.MsgSelectChain; type MsgSelectChain = ygopro.StocGameMessage.MsgSelectChain;
export default (selectChain: MsgSelectChain, dispatch: AppDispatch) => { export default (selectChain: MsgSelectChain) => {
const player = selectChain.player; const player = selectChain.player;
const spCount = selectChain.special_count; const spCount = selectChain.special_count;
const forced = selectChain.forced; const forced = selectChain.forced;
...@@ -71,11 +58,6 @@ export default (selectChain: MsgSelectChain, dispatch: AppDispatch) => { ...@@ -71,11 +58,6 @@ export default (selectChain: MsgSelectChain, dispatch: AppDispatch) => {
case 3: { case 3: {
// 处理强制发动的卡 // 处理强制发动的卡
// dispatch(setCheckCardModalMinMax({ min: 1, max: 1 }));
// dispatch(setCheckCardModalOnSubmit("sendSelectChainResponse"));
// dispatch(setCheckCardMOdalCancelAble(!forced));
// dispatch(setCheckCardModalCancelResponse(-1));
messageStore.checkCardModal.selectMin = 1; messageStore.checkCardModal.selectMin = 1;
messageStore.checkCardModal.selectMax = 1; messageStore.checkCardModal.selectMax = 1;
messageStore.checkCardModal.onSubmit = "sendSelectChainResponse"; messageStore.checkCardModal.onSubmit = "sendSelectChainResponse";
...@@ -83,35 +65,16 @@ export default (selectChain: MsgSelectChain, dispatch: AppDispatch) => { ...@@ -83,35 +65,16 @@ export default (selectChain: MsgSelectChain, dispatch: AppDispatch) => {
messageStore.checkCardModal.cancelResponse = -1; messageStore.checkCardModal.cancelResponse = -1;
for (const chain of chains) { for (const chain of chains) {
// const tagName = CardZoneToChinese(chain.location.location); fetchCheckCardMeta(chain.location.location, {
// dispatch(
// fetchCheckCardMeta({
// tagName,
// option: {
// code: chain.code,
// location: chain.location,
// response: chain.response,
// effectDescCode: chain.effect_description,
// },
// })
// );
FIXME_fetchCheckCardMeta(chain.location.location, {
code: chain.code, code: chain.code,
location: chain.location, location: chain.location,
response: chain.response, response: chain.response,
effectDescCode: chain.effect_description, effectDescCode: chain.effect_description,
}); });
} }
// dispatch( fetchSelectHintMeta({
// fetchSelectHintMeta({
// selectHintData: 203,
// })
// );
FIXME_fetchSelectHintMeta({
selectHintData: 203, selectHintData: 203,
}); });
// dispatch(setCheckCardModalIsOpen(true));
messageStore.checkCardModal.isOpen = true; messageStore.checkCardModal.isOpen = true;
break; break;
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { setCheckCounter } from "@/reducers/duel/mod"; import { getCardByLocation, messageStore } from "@/stores";
import { AppDispatch } from "@/store";
import { getCardByLocation, messageStore } from "@/valtioStores";
type MsgSelectCounter = ygopro.StocGameMessage.MsgSelectCounter; type MsgSelectCounter = ygopro.StocGameMessage.MsgSelectCounter;
export default (selectCounter: MsgSelectCounter, dispatch: AppDispatch) => { export default (selectCounter: MsgSelectCounter) => {
// dispatch(setCheckCounter(selectCounter.toObject()));
messageStore.checkCounterModal.counterType = selectCounter.counter_type; messageStore.checkCounterModal.counterType = selectCounter.counter_type;
messageStore.checkCounterModal.min = selectCounter.min; messageStore.checkCounterModal.min = selectCounter.min;
messageStore.checkCounterModal.options = selectCounter.options!.map( messageStore.checkCounterModal.options = selectCounter.options!.map(
......
import { ygopro } from "@/api"; import { fetchStrings, ygopro } from "@/api";
import { CardMeta, fetchCard } from "@/api/cards"; import { CardMeta, fetchCard } from "@/api/cards";
import { fetchStrings } from "@/api/strings"; import { messageStore } from "@/stores";
import { setYesNoModalIsOpen } from "@/reducers/duel/mod";
import { fetchYesNoMeta } from "@/reducers/duel/modal/mod";
import { AppDispatch } from "@/store";
import { getCardByLocation, messageStore } from "@/valtioStores";
import { CardZoneToChinese } from "./util"; import { CardZoneToChinese } from "./util";
type MsgSelectEffectYn = ygopro.StocGameMessage.MsgSelectEffectYn; type MsgSelectEffectYn = ygopro.StocGameMessage.MsgSelectEffectYn;
// 这里改成了 async 不知道有没有影响 // 这里改成了 async 不知道有没有影响
export default async ( export default async (selectEffectYn: MsgSelectEffectYn) => {
selectEffectYn: MsgSelectEffectYn,
dispatch: AppDispatch
) => {
const player = selectEffectYn.player; const player = selectEffectYn.player;
const code = selectEffectYn.code; const code = selectEffectYn.code;
const location = selectEffectYn.location; const location = selectEffectYn.location;
...@@ -47,7 +40,6 @@ export default async ( ...@@ -47,7 +40,6 @@ export default async (
// }) // })
// ); // );
// TODO: 国际化文案 // TODO: 国际化文案
dispatch(setYesNoModalIsOpen(true));
const desc = fetchStrings("!system", effect_description); const desc = fetchStrings("!system", effect_description);
const meta = await fetchCard(code); const meta = await fetchCard(code);
......
import { ActionCreatorWithPayload } from "@reduxjs/toolkit";
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { Interactivity, InteractType } from "@/reducers/duel/generic";
import {
addBanishedZoneIdleInteractivities,
addExtraDeckIdleInteractivities,
addGraveyardIdleInteractivities,
addHandsIdleInteractivity,
addMagicIdleInteractivities,
addMonsterIdleInteractivities,
clearAllIdleInteractivities,
setEnableBp,
setEnableEp,
} from "@/reducers/duel/mod";
import { AppDispatch } from "@/store";
import { import {
clearAllIdleInteractivities as FIXME_clearAllIdleInteractivities, clearAllIdleInteractivities as clearAllIdleInteractivities,
type Interactivity,
InteractType,
matStore, matStore,
} from "@/valtioStores"; } from "@/stores";
import MsgSelectIdleCmd = ygopro.StocGameMessage.MsgSelectIdleCmd; import MsgSelectIdleCmd = ygopro.StocGameMessage.MsgSelectIdleCmd;
export default (selectIdleCmd: MsgSelectIdleCmd, dispatch: AppDispatch) => { export default (selectIdleCmd: MsgSelectIdleCmd) => {
const player = selectIdleCmd.player; const player = selectIdleCmd.player;
const cmds = selectIdleCmd.idle_cmds; const cmds = selectIdleCmd.idle_cmds;
// 先清掉之前的互动性 // 先清掉之前的互动性
// dispatch(clearAllIdleInteractivities(player)); clearAllIdleInteractivities(player);
FIXME_clearAllIdleInteractivities(player);
// const dispatcher = (
// idleData: MsgSelectIdleCmd.IdleCmd.IdleData,
// interactType: InteractType | undefined,
// actionCreator: ActionCreatorWithPayload<
// {
// player: number;
// sequence: number;
// interactivity: Interactivity<number>;
// },
// string
// >
// ) => {
// const cardInfo = idleData.card_info;
// if (interactType === InteractType.ACTIVATE) {
// // 发动效果会多一个字段
// dispatch(
// actionCreator({
// player,
// sequence: cardInfo.sequence,
// interactivity: {
// interactType,
// activateIndex: idleData.effect_description,
// response: idleData.response,
// },
// })
// );
// } else if (interactType) {
// dispatch(
// actionCreator({
// player,
// sequence: cardInfo.sequence,
// interactivity: { interactType, response: idleData.response },
// })
// );
// } else {
// console.log(`InteractType undefined`);
// }
// };
cmds.forEach((cmd) => { cmds.forEach((cmd) => {
const interactType = idleTypeToInteractType(cmd.idle_type); const interactType = idleTypeToInteractType(cmd.idle_type);
...@@ -74,7 +21,7 @@ export default (selectIdleCmd: MsgSelectIdleCmd, dispatch: AppDispatch) => { ...@@ -74,7 +21,7 @@ export default (selectIdleCmd: MsgSelectIdleCmd, dispatch: AppDispatch) => {
cmd.idle_datas.forEach((data) => { cmd.idle_datas.forEach((data) => {
const { location, sequence } = data.card_info; const { location, sequence } = data.card_info;
// valtio代码从 ./selectBattleCmd.ts 复制过来的 // valtio: 代码从 ./selectBattleCmd.ts 复制过来的
if (interactType) { if (interactType) {
const map: Partial< const map: Partial<
Record<InteractType, undefined | Partial<Interactivity<number>>> Record<InteractType, undefined | Partial<Interactivity<number>>>
...@@ -93,48 +40,9 @@ export default (selectIdleCmd: MsgSelectIdleCmd, dispatch: AppDispatch) => { ...@@ -93,48 +40,9 @@ export default (selectIdleCmd: MsgSelectIdleCmd, dispatch: AppDispatch) => {
} else { } else {
console.warn(`Undefined InteractType`); console.warn(`Undefined InteractType`);
} }
// switch (location) {
// case ygopro.CardZone.HAND: {
// dispatcher(data, interactType, addHandsIdleInteractivity);
// break;
// }
// case ygopro.CardZone.MZONE: {
// dispatcher(data, interactType, addMonsterIdleInteractivities);
// break;
// }
// case ygopro.CardZone.SZONE: {
// dispatcher(data, interactType, addMagicIdleInteractivities);
// break;
// }
// case ygopro.CardZone.GRAVE: {
// dispatcher(data, interactType, addGraveyardIdleInteractivities);
// break;
// }
// case ygopro.CardZone.REMOVED: {
// dispatcher(data, interactType, addBanishedZoneIdleInteractivities);
// break;
// }
// case ygopro.CardZone.EXTRA: {
// dispatcher(data, interactType, addExtraDeckIdleInteractivities);
// break;
// }
// default: {
// console.log(`Unhandled zone type: ${location}`);
// }
// }
}); });
}); });
// dispatch(setEnableBp(selectIdleCmd.enable_bp));
// dispatch(setEnableEp(selectIdleCmd.enable_ep));
matStore.phase.enableBp = selectIdleCmd.enable_bp; matStore.phase.enableBp = selectIdleCmd.enable_bp;
matStore.phase.enableEp = selectIdleCmd.enable_ep; matStore.phase.enableEp = selectIdleCmd.enable_ep;
}; };
......
import { fetchCard, getCardStr, ygopro } from "@/api"; import { fetchCard, getCardStr, ygopro } from "@/api";
import { setOptionModalIsOpen } from "@/reducers/duel/mod";
import { fetchOptionMeta } from "@/reducers/duel/modal/mod";
import { AppDispatch } from "@/store";
import MsgSelectOption = ygopro.StocGameMessage.MsgSelectOption; import MsgSelectOption = ygopro.StocGameMessage.MsgSelectOption;
import { messageStore } from "@/valtioStores"; import { messageStore } from "@/stores";
export default async (selectOption: MsgSelectOption, dispatch: AppDispatch) => { export default async (selectOption: MsgSelectOption) => {
const player = selectOption.player; const player = selectOption.player;
const options = selectOption.options; const options = selectOption.options;
// for (let option of options) {
// dispatch(fetchOptionMeta(option));
// }
// dispatch(setOptionModalIsOpen(true));
await Promise.all( await Promise.all(
options.map(async ({ code, response }) => { options.map(async ({ code, response }) => {
const meta = await fetchCard(code >> 4); const meta = await fetchCard(code >> 4);
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { AppDispatch } from "@/store"; import { InteractType, matStore } from "@/stores";
import MsgSelectPlace = ygopro.StocGameMessage.MsgSelectPlace;
import {
addMagicPlaceInteractivities,
addMonsterPlaceInteractivities,
} from "@/reducers/duel/mod";
import { InteractType, valtioStore } from "@/valtioStores";
const { matStore } = valtioStore; type MsgSelectPlace = ygopro.StocGameMessage.MsgSelectPlace;
export default (selectPlace: MsgSelectPlace, dispatch: AppDispatch) => { export default (selectPlace: MsgSelectPlace) => {
if (selectPlace.count != 1) { if (selectPlace.count != 1) {
console.warn(`Unhandled case: ${selectPlace}`); console.warn(`Unhandled case: ${selectPlace}`);
return; return;
} }
for (const place of selectPlace.places) { for (const place of selectPlace.places) {
switch (place.zone) { switch (place.zone) {
case ygopro.CardZone.MZONE: { case ygopro.CardZone.MZONE: {
// dispatch(
// addMonsterPlaceInteractivities([place.controler, place.sequence])
// );
matStore.monsters matStore.monsters
.of(place.controler) .of(place.controler)
.setPlaceInteractivityType( .setPlaceInteractivityType(
...@@ -31,9 +21,6 @@ export default (selectPlace: MsgSelectPlace, dispatch: AppDispatch) => { ...@@ -31,9 +21,6 @@ export default (selectPlace: MsgSelectPlace, dispatch: AppDispatch) => {
break; break;
} }
case ygopro.CardZone.SZONE: { case ygopro.CardZone.SZONE: {
// dispatch(
// addMagicPlaceInteractivities([place.controler, place.sequence])
// );
matStore.magics matStore.magics
.of(place.controler) .of(place.controler)
.setPlaceInteractivityType( .setPlaceInteractivityType(
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { import { messageStore } from "@/stores";
setPositionModalIsOpen,
setPositionModalPositions,
} from "@/reducers/duel/mod";
import { AppDispatch } from "@/store";
import { messageStore } from "@/valtioStores";
type MsgSelectPosition = ygopro.StocGameMessage.MsgSelectPosition; type MsgSelectPosition = ygopro.StocGameMessage.MsgSelectPosition;
export default (selectPosition: MsgSelectPosition, dispatch: AppDispatch) => { export default (selectPosition: MsgSelectPosition) => {
const player = selectPosition.player; const player = selectPosition.player;
const positions = selectPosition.positions; const positions = selectPosition.positions;
// dispatch(
// setPositionModalPositions(positions.map((position) => position.position))
// );
// dispatch(setPositionModalIsOpen(true));
messageStore.positionModal.positions = positions.map( messageStore.positionModal.positions = positions.map(
(position) => position.position (position) => position.position
); );
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { import { fetchCheckCardMetasV3, messageStore } from "@/stores";
setCheckCardModalV3AllLevel,
setCheckCardModalV3IsOpen,
setCheckCardModalV3MinMax,
setCheckCardModalV3OverFlow,
} from "@/reducers/duel/mod";
import { fetchCheckCardMetasV3 } from "@/reducers/duel/modal/checkCardModalV3Slice";
import { AppDispatch } from "@/store";
import {
fetchCheckCardMetasV3 as FIXME_fetchCheckCardMetasV3,
messageStore,
} from "@/valtioStores";
type MsgSelectSum = ygopro.StocGameMessage.MsgSelectSum; type MsgSelectSum = ygopro.StocGameMessage.MsgSelectSum;
export default (selectSum: MsgSelectSum, dispatch: AppDispatch) => { export default (selectSum: MsgSelectSum) => {
// dispatch(setCheckCardModalV3OverFlow(selectSum.overflow != 0));
messageStore.checkCardModalV3.overflow = selectSum.overflow != 0; messageStore.checkCardModalV3.overflow = selectSum.overflow != 0;
// dispatch(setCheckCardModalV3AllLevel(selectSum.level_sum));
messageStore.checkCardModalV3.allLevel = selectSum.level_sum; messageStore.checkCardModalV3.allLevel = selectSum.level_sum;
// dispatch(
// setCheckCardModalV3MinMax({ min: selectSum.min, max: selectSum.max })
// );
messageStore.checkCardModalV3.selectMin = selectSum.min; messageStore.checkCardModalV3.selectMin = selectSum.min;
messageStore.checkCardModalV3.selectMax = selectSum.max; messageStore.checkCardModalV3.selectMax = selectSum.max;
// dispatch(
// fetchCheckCardMetasV3({ fetchCheckCardMetasV3({
// mustSelect: true,
// options: selectSum.must_select_cards,
// })
// );
FIXME_fetchCheckCardMetasV3({
mustSelect: true, mustSelect: true,
options: selectSum.must_select_cards, options: selectSum.must_select_cards,
}); });
// dispatch(
// fetchCheckCardMetasV3({ fetchCheckCardMetasV3({
// mustSelect: false,
// options: selectSum.selectable_cards,
// })
// );
FIXME_fetchCheckCardMetasV3({
mustSelect: false, mustSelect: false,
options: selectSum.selectable_cards, options: selectSum.selectable_cards,
}); });
// dispatch(setCheckCardModalV3IsOpen(true));
messageStore.checkCardModalV3.isOpen = true; messageStore.checkCardModalV3.isOpen = true;
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { import { fetchCheckCardMetasV3, messageStore } from "@/stores";
setCheckCardModalV3AllLevel,
setCheckCardModalV3IsOpen,
setCheckCardModalV3MinMax,
setCheckCardModalV3OverFlow,
} from "@/reducers/duel/mod";
import { fetchCheckCardMetasV3 } from "@/reducers/duel/modal/checkCardModalV3Slice";
import { AppDispatch } from "@/store";
import {
fetchCheckCardMetasV3 as FIXME_fetchCheckCardMetasV3,
messageStore,
} from "@/valtioStores";
type MsgSelectTribute = ygopro.StocGameMessage.MsgSelectTribute; type MsgSelectTribute = ygopro.StocGameMessage.MsgSelectTribute;
export default (selectTribute: MsgSelectTribute, dispatch: AppDispatch) => { export default (selectTribute: MsgSelectTribute) => {
// TODO: 当玩家选择卡数大于`max`时,是否也合法? // TODO: 当玩家选择卡数大于`max`时,是否也合法?
// dispatch(setCheckCardModalV3OverFlow(true));
messageStore.checkCardModalV3.overflow = true; messageStore.checkCardModalV3.overflow = true;
// dispatch(setCheckCardModalV3AllLevel(0));
messageStore.checkCardModalV3.allLevel = 0; messageStore.checkCardModalV3.allLevel = 0;
// dispatch(
// setCheckCardModalV3MinMax({
// min: selectTribute.min,
// max: selectTribute.max,
// })
// );
messageStore.checkCardModalV3.selectMin = selectTribute.min; messageStore.checkCardModalV3.selectMin = selectTribute.min;
messageStore.checkCardModalV3.selectMax = selectTribute.max; messageStore.checkCardModalV3.selectMax = selectTribute.max;
// dispatch(
// fetchCheckCardMetasV3({ fetchCheckCardMetasV3({
// mustSelect: false,
// options: selectTribute.selectable_cards.map((card) => {
// return {
// code: card.code,
// location: card.location,
// level1: card.level,
// level2: card.level,
// response: card.response,
// };
// }),
// })
// );
FIXME_fetchCheckCardMetasV3({
mustSelect: false, mustSelect: false,
options: selectTribute.selectable_cards.map((card) => { options: selectTribute.selectable_cards.map((card) => {
return { return {
...@@ -54,6 +22,6 @@ export default (selectTribute: MsgSelectTribute, dispatch: AppDispatch) => { ...@@ -54,6 +22,6 @@ export default (selectTribute: MsgSelectTribute, dispatch: AppDispatch) => {
}; };
}), }),
}); });
// dispatch(setCheckCardModalV3IsOpen(true));
messageStore.checkCardModalV3.isOpen = true; messageStore.checkCardModalV3.isOpen = true;
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { import { fetchCheckCardMetasV2, messageStore } from "@/stores";
setCheckCardModalV2CancelAble,
setCheckCardModalV2FinishAble,
setCheckCardModalV2IsOpen,
setCheckCardModalV2MinMax,
setCheckCardModalV2ResponseAble,
} from "@/reducers/duel/mod";
import { fetchCheckCardMetasV2 } from "@/reducers/duel/modal/checkCardModalV2Slice";
import { AppDispatch } from "@/store";
import {
fetchCheckCardMetasV2 as FIXME_fetchCheckCardMetasV2,
messageStore,
} from "@/valtioStores";
type MsgSelectUnselectCard = ygopro.StocGameMessage.MsgSelectUnselectCard; type MsgSelectUnselectCard = ygopro.StocGameMessage.MsgSelectUnselectCard;
export default ( export default ({
{
finishable, finishable,
cancelable, cancelable,
min, min,
max, max,
selectable_cards: selectableCards, selectable_cards: selectableCards,
selected_cards: selectedCards, selected_cards: selectedCards,
}: MsgSelectUnselectCard, }: MsgSelectUnselectCard) => {
dispatch: AppDispatch
) => {
// dispatch(setCheckCardModalV2IsOpen(true));
// dispatch(setCheckCardModalV2FinishAble(finishable));
// dispatch(setCheckCardModalV2CancelAble(cancelable));
// dispatch(setCheckCardModalV2MinMax({ min, max }));
messageStore.checkCardModalV2.isOpen = true; messageStore.checkCardModalV2.isOpen = true;
messageStore.checkCardModalV2.finishAble = finishable; messageStore.checkCardModalV2.finishAble = finishable;
messageStore.checkCardModalV2.cancelAble = cancelable; messageStore.checkCardModalV2.cancelAble = cancelable;
messageStore.checkCardModalV2.selectMin = min; messageStore.checkCardModalV2.selectMin = min;
messageStore.checkCardModalV2.selectMax = max; messageStore.checkCardModalV2.selectMax = max;
// dispatch( fetchCheckCardMetasV2({
// fetchCheckCardMetasV2({
// selected: false,
// options: selectableCards.map((card) => {
// return {
// code: card.code,
// location: card.location,
// response: card.response,
// };
// }),
// })
// );
FIXME_fetchCheckCardMetasV2({
selected: false, selected: false,
options: selectableCards.map((card) => { options: selectableCards.map((card) => {
return { return {
...@@ -61,20 +28,7 @@ export default ( ...@@ -61,20 +28,7 @@ export default (
}), }),
}); });
// dispatch( fetchCheckCardMetasV2({
// fetchCheckCardMetasV2({
// selected: true,
// options: selectedCards.map((card) => {
// return {
// code: card.code,
// location: card.location,
// response: card.response,
// };
// }),
// })
// );
FIXME_fetchCheckCardMetasV2({
selected: true, selected: true,
options: selectedCards.map((card) => { options: selectedCards.map((card) => {
return { return {
...@@ -85,7 +39,5 @@ export default ( ...@@ -85,7 +39,5 @@ export default (
}), }),
}); });
// dispatch(setCheckCardModalV2ResponseAble(true));
messageStore.checkCardModalV2.responseable = true; messageStore.checkCardModalV2.responseable = true;
}; };
import { getStrings, ygopro } from "@/api"; import { getStrings, ygopro } from "@/api";
import { setYesNoModalIsOpen } from "@/reducers/duel/mod"; import { messageStore } from "@/stores";
import { fetchYesNoMetaWithEffecDesc } from "@/reducers/duel/modal/yesNoModalSlice";
import { AppDispatch } from "@/store";
import { messageStore } from "@/valtioStores";
type MsgSelectYesNo = ygopro.StocGameMessage.MsgSelectYesNo; type MsgSelectYesNo = ygopro.StocGameMessage.MsgSelectYesNo;
export default async (selectYesNo: MsgSelectYesNo, dispatch: AppDispatch) => { export default async (selectYesNo: MsgSelectYesNo) => {
const player = selectYesNo.player; const player = selectYesNo.player;
const effect_description = selectYesNo.effect_description; const effect_description = selectYesNo.effect_description;
// dispatch(fetchYesNoMetaWithEffecDesc(effect_description));
// dispatch(setYesNoModalIsOpen(true));
messageStore.yesNoModal.msg = await getStrings(effect_description); messageStore.yesNoModal.msg = await getStrings(effect_description);
messageStore.yesNoModal.isOpen = true; messageStore.yesNoModal.isOpen = true;
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/stores";
import { AppDispatch } from "@/store";
import { fetchEsHintMeta as FIXME_fetchEsHintMeta } from "@/valtioStores";
export default (_set: ygopro.StocGameMessage.MsgSet, dispatch: AppDispatch) => { export default (_set: ygopro.StocGameMessage.MsgSet) => {
// dispatch(fetchEsHintMeta({ originMsg: 1601 })); fetchEsHintMeta({ originMsg: 1601 });
FIXME_fetchEsHintMeta({ originMsg: 1601 });
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { updateHandsMeta } from "@/reducers/duel/handsSlice"; import { matStore } from "@/stores";
import { AppDispatch } from "@/store";
import MsgShuffleHand = ygopro.StocGameMessage.MsgShuffleHand;
import { matStore } from "@/valtioStores"; type MsgShuffleHand = ygopro.StocGameMessage.MsgShuffleHand;
export default (shuffleHand: MsgShuffleHand, dispatch: AppDispatch) => {
// dispatch(
// updateHandsMeta({ controler: shuffleHand.player, codes: shuffleHand.hands })
// );
export default (shuffleHand: MsgShuffleHand) => {
const { hands: codes, player: controller } = shuffleHand; const { hands: codes, player: controller } = shuffleHand;
const metas = codes.map((code) => { const metas = codes.map((code) => {
......
import { fetchCard, ygopro } from "@/api"; import { fetchCard, ygopro } from "@/api";
import { setSortCardModalIsOpen } from "@/reducers/duel/mod"; import { messageStore } from "@/stores";
import { fetchSortCardMeta } from "@/reducers/duel/modal/sortCardModalSlice";
import { AppDispatch } from "@/store";
import MsgSortCard = ygopro.StocGameMessage.MsgSortCard;
import { messageStore } from "@/valtioStores"; type MsgSortCard = ygopro.StocGameMessage.MsgSortCard;
export default async (sortCard: MsgSortCard, dispatch: AppDispatch) => {
// for (const option of sortCard.options) {
// dispatch(fetchSortCardMeta(option.toObject()));
// }
// dispatch(setSortCardModalIsOpen(true));
export default async (sortCard: MsgSortCard) => {
await Promise.all( await Promise.all(
sortCard.options.map(async ({ code, response }) => { sortCard.options.map(async ({ code, response }) => {
const meta = await fetchCard(code!, true); const meta = await fetchCard(code!, true);
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/stores";
import { AppDispatch } from "@/store";
import { fetchEsHintMeta as FIXME_fetchEsHintMeta } from "@/valtioStores";
export default ( export default (_: ygopro.StocGameMessage.MsgSpSummoned) => {
_: ygopro.StocGameMessage.MsgSpSummoned, fetchEsHintMeta({ originMsg: 1606 });
dispatch: AppDispatch
) => {
// dispatch(fetchEsHintMeta({ originMsg: 1606 }));
FIXME_fetchEsHintMeta({ originMsg: 1606 });
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/stores";
import { AppDispatch } from "@/store"; export default (spSummoning: ygopro.StocGameMessage.MsgSpSummoning) => {
import { fetchEsHintMeta as FIXME_fetchEsHintMeta } from "@/valtioStores"; fetchEsHintMeta({
export default (
spSummoning: ygopro.StocGameMessage.MsgSpSummoning,
dispatch: AppDispatch
) => {
// dispatch(
// fetchEsHintMeta({
// originMsg: "「[?]」特殊召唤宣言时",
// cardID: spSummoning.code,
// })
// );
FIXME_fetchEsHintMeta({
originMsg: "「[?]」特殊召唤宣言时", originMsg: "「[?]」特殊召唤宣言时",
cardID: spSummoning.code, cardID: spSummoning.code,
}); });
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { import { store } from "@/stores";
infoInit,
initBanishedZone,
initDeck,
initGraveyard,
initHint,
initMagics,
initMonsters,
setSelfType,
} from "@/reducers/duel/mod";
import { AppDispatch } from "@/store";
import { valtioStore } from "@/valtioStores";
const { matStore } = valtioStore; const { matStore } = store;
export default (
start: ygopro.StocGameMessage.MsgStart,
dispatch: AppDispatch
) => {
// dispatch(setSelfType(start.playerType));
export default (start: ygopro.StocGameMessage.MsgStart) => {
matStore.selfType = start.playerType; matStore.selfType = start.playerType;
matStore.initInfo.set(0, { matStore.initInfo.set(0, {
...@@ -33,44 +17,6 @@ export default ( ...@@ -33,44 +17,6 @@ export default (
extraSize: start.extraSize2, extraSize: start.extraSize2,
}); });
// dispatch(
// infoInit([
// 0,
// {
// life: start.life1,
// deckSize: start.deckSize1,
// extraSize: start.extraSize1,
// },
// ])
// );
// dispatch(
// infoInit([
// 1,
// {
// life: start.life2,
// deckSize: start.deckSize2,
// extraSize: start.extraSize2,
// },
// ])
// );
// >>> 删除 >>>
// dispatch(initMonsters(0));
// dispatch(initMonsters(1));
// dispatch(initMagics(0));
// dispatch(initMagics(1));
// dispatch(initGraveyard(0));
// dispatch(initGraveyard(1));
// dispatch(initDeck({ player: 0, deskSize: start.deckSize1 }));
// dispatch(initDeck({ player: 1, deskSize: start.deckSize2 }));
// dispatch(initBanishedZone(0));
// dispatch(initBanishedZone(1));
// <<< 删除 <<<
// 上面的删除就可以了
matStore.monsters.of(0).forEach((x) => (x.location.controler = 0)); matStore.monsters.of(0).forEach((x) => (x.location.controler = 0));
matStore.monsters.of(1).forEach((x) => (x.location.controler = 1)); matStore.monsters.of(1).forEach((x) => (x.location.controler = 1));
matStore.magics.of(0).forEach((x) => (x.location.controler = 0)); matStore.magics.of(0).forEach((x) => (x.location.controler = 0));
...@@ -78,5 +24,4 @@ export default ( ...@@ -78,5 +24,4 @@ export default (
matStore.decks.of(0).add(Array(start.deckSize1).fill(0)); matStore.decks.of(0).add(Array(start.deckSize1).fill(0));
matStore.decks.of(1).add(Array(start.deckSize2).fill(0)); matStore.decks.of(1).add(Array(start.deckSize2).fill(0));
// dispatch(initHint()); // 直接删除
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/stores";
import { AppDispatch } from "@/store";
import { fetchEsHintMeta as FIXME_fetchEsHintMeta } from "@/valtioStores";
export default ( export default (_: ygopro.StocGameMessage.MsgSummoned) => {
_: ygopro.StocGameMessage.MsgSummoned, fetchEsHintMeta({ originMsg: 1604 });
dispatch: AppDispatch
) => {
// dispatch(fetchEsHintMeta({ originMsg: 1604 }));
FIXME_fetchEsHintMeta({ originMsg: 1604 });
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/stores";
import { AppDispatch } from "@/store";
import { fetchEsHintMeta as FIXME_fetchEsHintMeta } from "@/valtioStores";
export default ( export default (summoning: ygopro.StocGameMessage.MsgSummoning) => {
summoning: ygopro.StocGameMessage.MsgSummoning, fetchEsHintMeta({
dispatch: AppDispatch
) => {
// dispatch(
// fetchEsHintMeta({
// originMsg: "「[?]」通常召唤宣言时",
// cardID: summoning.code,
// })
// );
FIXME_fetchEsHintMeta({
originMsg: "「[?]」通常召唤宣言时", originMsg: "「[?]」通常召唤宣言时",
cardID: summoning.code, cardID: summoning.code,
}); });
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/stores";
import { AppDispatch } from "@/store";
import { fetchEsHintMeta as FIXME_fetchEsHintMeta } from "@/valtioStores";
export default ( export default (_swap: ygopro.StocGameMessage.MsgSwap) => {
_swap: ygopro.StocGameMessage.MsgSwap, fetchEsHintMeta({ originMsg: 1602 });
dispatch: AppDispatch
) => {
// dispatch(fetchEsHintMeta({ originMsg: 1602 }));
FIXME_fetchEsHintMeta({ originMsg: 1602 });
}; };
import { ygopro } from "@/api"; import { sendTimeConfirm, ygopro } from "@/api";
import { sendTimeConfirm } from "@/api/ocgcore/ocgHelper"; import { matStore } from "@/stores";
import { updateTimeLimit } from "@/reducers/duel/mod";
import { store } from "@/store";
import { matStore } from "@/valtioStores";
export default function handleTimeLimit(timeLimit: ygopro.StocTimeLimit) { export default function handleTimeLimit(timeLimit: ygopro.StocTimeLimit) {
// const dispatch = store.dispatch;
// dispatch(updateTimeLimit([timeLimit.player, timeLimit.left_time]));
matStore.timeLimits.set(timeLimit.player, timeLimit.left_time); matStore.timeLimits.set(timeLimit.player, timeLimit.left_time);
sendTimeConfirm(); sendTimeConfirm();
} }
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { setUnimplemented } from "@/reducers/duel/mod"; import { matStore } from "@/stores";
import { AppDispatch } from "@/store";
import { matStore } from "@/valtioStores";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
export default ( export default (unimplemented: ygopro.StocGameMessage.MsgUnimplemented) => {
unimplemented: ygopro.StocGameMessage.MsgUnimplemented,
dispatch: AppDispatch
) => {
if (!NeosConfig.unimplementedWhiteList.includes(unimplemented.command)) { if (!NeosConfig.unimplementedWhiteList.includes(unimplemented.command)) {
// dispatch(setUnimplemented(unimplemented.command));
matStore.unimplemented = unimplemented.command; matStore.unimplemented = unimplemented.command;
} }
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { updateMonsterCounters } from "@/reducers/duel/mod"; import { getCardByLocation } from "@/stores";
import { AppDispatch } from "@/store";
import { getCardByLocation } from "@/valtioStores";
type MsgUpdateCounter = ygopro.StocGameMessage.MsgUpdateCounter; type MsgUpdateCounter = ygopro.StocGameMessage.MsgUpdateCounter;
export default (updateCounter: MsgUpdateCounter, dispatch: AppDispatch) => { export default (updateCounter: MsgUpdateCounter) => {
// dispatch(updateMonsterCounters(updateCounter.toObject()));
const { location, count, action_type: counterType } = updateCounter; const { location, count, action_type: counterType } = updateCounter;
const target = getCardByLocation(location); // 不太确定这个后面能不能相应,我不好说 const target = getCardByLocation(location); // 不太确定这个后面能不能相应,我不好说
if (target) { if (target) {
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { updateFieldData } from "@/reducers/duel/mod";
import { AppDispatch } from "@/store";
import MsgUpdateData = ygopro.StocGameMessage.MsgUpdateData; import MsgUpdateData = ygopro.StocGameMessage.MsgUpdateData;
import { matStore } from "@/valtioStores"; import { matStore } from "@/stores";
export default (updateData: MsgUpdateData, dispatch: AppDispatch) => {
// dispatch(updateFieldData(updateData.toObject()));
export default (updateData: MsgUpdateData) => {
const { player: controller, zone, actions } = updateData; const { player: controller, zone, actions } = updateData;
if (controller !== undefined && zone !== undefined && actions !== undefined) { if (controller !== undefined && zone !== undefined && actions !== undefined) {
const field = matStore.in(zone).of(controller); const field = matStore.in(zone).of(controller);
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta, matStore } from "@/stores";
import { updateHp } from "@/reducers/duel/mod";
import { AppDispatch } from "@/store";
import {
fetchEsHintMeta as FIXME_fetchEsHintMeta,
matStore,
} from "@/valtioStores";
import MsgUpdateHp = ygopro.StocGameMessage.MsgUpdateHp; import MsgUpdateHp = ygopro.StocGameMessage.MsgUpdateHp;
export default (msgUpdateHp: MsgUpdateHp, dispatch: AppDispatch) => { export default (msgUpdateHp: MsgUpdateHp) => {
if (msgUpdateHp.type_ == MsgUpdateHp.ActionType.DAMAGE) { if (msgUpdateHp.type_ == MsgUpdateHp.ActionType.DAMAGE) {
// dispatch(fetchEsHintMeta({ originMsg: "玩家收到伤害时" })); // TODO: i18n fetchEsHintMeta({ originMsg: "玩家收到伤害时" }); // TODO: i18n
FIXME_fetchEsHintMeta({ originMsg: "玩家收到伤害时" });
matStore.initInfo.of(msgUpdateHp.player).life -= msgUpdateHp.value; matStore.initInfo.of(msgUpdateHp.player).life -= msgUpdateHp.value;
} else if (msgUpdateHp.type_ == MsgUpdateHp.ActionType.RECOVER) { } else if (msgUpdateHp.type_ == MsgUpdateHp.ActionType.RECOVER) {
// dispatch(fetchEsHintMeta({ originMsg: "玩家生命值回复时" })); // TODO: i18n fetchEsHintMeta({ originMsg: "玩家生命值回复时" }); // TODO: i18n
FIXME_fetchEsHintMeta({ originMsg: "玩家生命值回复时" });
matStore.initInfo.of(msgUpdateHp.player).life += msgUpdateHp.value; matStore.initInfo.of(msgUpdateHp.player).life += msgUpdateHp.value;
} }
dispatch(updateHp(msgUpdateHp)); // 可以删除了
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { clearAllIdleInteractivities, setWaiting } from "@/reducers/duel/mod";
import { AppDispatch } from "@/store";
import { import {
clearAllIdleInteractivities as FIXME_clearAllIdleInteractivities, clearAllIdleInteractivities as clearAllIdleInteractivities,
matStore, matStore,
} from "@/valtioStores"; } from "@/stores";
export default ( export default (_wait: ygopro.StocGameMessage.MsgWait) => {
_wait: ygopro.StocGameMessage.MsgWait, clearAllIdleInteractivities(0);
dispatch: AppDispatch clearAllIdleInteractivities(1);
) => {
// dispatch(clearAllIdleInteractivities(0));
// dispatch(clearAllIdleInteractivities(1));
// dispatch(setWaiting(true));
FIXME_clearAllIdleInteractivities(0);
FIXME_clearAllIdleInteractivities(1);
matStore.waiting = true; matStore.waiting = true;
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { setResult } from "@/reducers/duel/mod"; import { matStore } from "@/stores";
import { AppDispatch } from "@/store";
import { matStore } from "@/valtioStores";
export default (win: ygopro.StocGameMessage.MsgWin, dispatch: AppDispatch) => { export default (win: ygopro.StocGameMessage.MsgWin) => {
// dispatch(setResult(win.type_));
matStore.result = win.type_; matStore.result = win.type_;
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { player0DeckInfo, player1DeckInfo } from "@/reducers/playerSlice"; import { playerStore } from "@/stores";
import { store } from "@/store";
import { playerStore } from "@/valtioStores";
// FIXME: player0 不一定是当前玩家 // FIXME: player0 不一定是当前玩家
export default function handleDeckCount(pb: ygopro.YgoStocMsg) { export default function handleDeckCount(pb: ygopro.YgoStocMsg) {
// const dispath = store.dispatch;
const deckCount = pb.stoc_deck_count; const deckCount = pb.stoc_deck_count;
// dispath(
// player0DeckInfo({
// mainCnt: deckCount.meMain,
// extraCnt: deckCount.meExtra,
// sideCnt: deckCount.meSide,
// })
// );
playerStore.player0.deckInfo = { playerStore.player0.deckInfo = {
mainCnt: deckCount.meMain, mainCnt: deckCount.meMain,
extraCnt: deckCount.meExtra, extraCnt: deckCount.meExtra,
sideCnt: deckCount.meSide, sideCnt: deckCount.meSide,
}; };
// dispath(
// player1DeckInfo({
// mainCnt: deckCount.opMain,
// extraCnt: deckCount.opExtra,
// sideCnt: deckCount.opSide,
// })
// );
playerStore.player1.deckInfo = { playerStore.player1.deckInfo = {
mainCnt: deckCount.opMain, mainCnt: deckCount.opMain,
extraCnt: deckCount.opExtra, extraCnt: deckCount.opExtra,
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { selectHandAble } from "@/reducers/moraSlice"; import { moraStore } from "@/stores";
import { store } from "@/store";
import { moraStore } from "@/valtioStores";
export default function handleSelectHand(_: ygopro.YgoStocMsg) { export default function handleSelectHand(_: ygopro.YgoStocMsg) {
// const dispatch = store.dispatch;
// dispatch(selectHandAble());
moraStore.selectHandAble = true; moraStore.selectHandAble = true;
} }
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { selectTpAble } from "@/reducers/moraSlice"; import { moraStore } from "@/stores";
import { store } from "@/store";
import { moraStore } from "@/valtioStores";
export default function handleSelectTp(_: ygopro.YgoStocMsg) { export default function handleSelectTp(_: ygopro.YgoStocMsg) {
// const dispatch = store.dispatch;
// dispatch(selectTpAble());
moraStore.selectTpAble = true; moraStore.selectTpAble = true;
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* 长连接建立事件订阅处理逻辑 * 长连接建立事件订阅处理逻辑
* *
* */ * */
import { sendJoinGame, sendPlayerInfo } from "@/api/ocgcore/ocgHelper"; import { sendJoinGame, sendPlayerInfo } from "@/api";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { postChat } from "@/reducers/chatSlice"; import { chatStore } from "@/stores";
import { store } from "@/store";
import { chatStore } from "@/valtioStores";
export default function handleChat(pb: ygopro.YgoStocMsg) { export default function handleChat(pb: ygopro.YgoStocMsg) {
// const dispatch = store.dispatch;
const chat = pb.stoc_chat; const chat = pb.stoc_chat;
// dispatch(postChat(chat.msg));
chatStore.message = chat.msg; chatStore.message = chat.msg;
} }
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { duelStart } from "@/reducers/moraSlice"; import { moraStore } from "@/stores";
import { store } from "@/store";
import { moraStore } from "@/valtioStores";
export default function handleDuelStart(_pb: ygopro.YgoStocMsg) { export default function handleDuelStart(_pb: ygopro.YgoStocMsg) {
// const dispatch = store.dispatch;
// dispatch(duelStart());
moraStore.duelStart = true; moraStore.duelStart = true;
} }
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { import { playerStore } from "@/stores";
observerIncrement,
player0Leave,
player0Update,
player1Leave,
player1Update,
} from "@/reducers/playerSlice";
import { store } from "@/store";
import { playerStore } from "@/valtioStores";
const READY_STATE = "ready"; const READY_STATE = "ready";
const NO_READY_STATE = "not ready"; const NO_READY_STATE = "not ready";
export default function handleHsPlayerChange(pb: ygopro.YgoStocMsg) { export default function handleHsPlayerChange(pb: ygopro.YgoStocMsg) {
// const dispatch = store.dispatch;
const change = pb.stoc_hs_player_change; const change = pb.stoc_hs_player_change;
if (change.pos > 1) { if (change.pos > 1) {
...@@ -35,42 +26,25 @@ export default function handleHsPlayerChange(pb: ygopro.YgoStocMsg) { ...@@ -35,42 +26,25 @@ export default function handleHsPlayerChange(pb: ygopro.YgoStocMsg) {
// todo // todo
// if (src === 0 && dst === 1) {
// setPlayer1(player0);
// setPlayer0({});
// } else if (src === 1 && dst === 0) {
// setPlayer0(player1);
// setPlayer1({});
// }
break; break;
} }
case ygopro.StocHsPlayerChange.State.READY: { case ygopro.StocHsPlayerChange.State.READY: {
// change.pos == 0
// ? dispatch(player0Update(READY_STATE))
// : dispatch(player1Update(READY_STATE));
playerStore[change.pos == 0 ? "player0" : "player1"].state = playerStore[change.pos == 0 ? "player0" : "player1"].state =
READY_STATE; READY_STATE;
break; break;
} }
case ygopro.StocHsPlayerChange.State.NO_READY: { case ygopro.StocHsPlayerChange.State.NO_READY: {
// change.pos == 0
// ? dispatch(player0Update(NO_READY_STATE))
// : dispatch(player1Update(NO_READY_STATE));
playerStore[change.pos == 0 ? "player0" : "player1"].state = playerStore[change.pos == 0 ? "player0" : "player1"].state =
NO_READY_STATE; NO_READY_STATE;
break; break;
} }
case ygopro.StocHsPlayerChange.State.LEAVE: { case ygopro.StocHsPlayerChange.State.LEAVE: {
// change.pos == 0 ? dispatch(player0Leave) : dispatch(player1Leave);
playerStore[change.pos == 0 ? "player0" : "player1"] = {}; playerStore[change.pos == 0 ? "player0" : "player1"] = {};
break; break;
} }
case ygopro.StocHsPlayerChange.State.TO_OBSERVER: { case ygopro.StocHsPlayerChange.State.TO_OBSERVER: {
// change.pos == 0 ? dispatch(player0Leave) : dispatch(player1Leave);
// dispatch(observerIncrement());
playerStore[change.pos == 0 ? "player0" : "player1"] = {}; // todo: 有没有必要? playerStore[change.pos == 0 ? "player0" : "player1"] = {}; // todo: 有没有必要?
playerStore.observerCount += 1; playerStore.observerCount += 1;
break; break;
......
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { player0Enter, player1Enter } from "@/reducers/playerSlice"; import { playerStore } from "@/stores";
import { store } from "@/store";
import { playerStore } from "@/valtioStores";
export default function handleHsPlayerEnter(pb: ygopro.YgoStocMsg) { export default function handleHsPlayerEnter(pb: ygopro.YgoStocMsg) {
// const dispatch = store.dispatch;
const name = pb.stoc_hs_player_enter.name; const name = pb.stoc_hs_player_enter.name;
const pos = pb.stoc_hs_player_enter.pos; const pos = pb.stoc_hs_player_enter.pos;
if (pos > 1) { if (pos > 1) {
console.log("Currently only supported 2v2 mode."); console.log("Currently only supported 2v2 mode.");
} else { } else {
// pos == 0 ? dispatch(player0Enter(name)) : dispatch(player1Enter(name));
playerStore[pos == 0 ? "player0" : "player1"].name = name; playerStore[pos == 0 ? "player0" : "player1"].name = name;
} }
} }
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { observerChange } from "@/reducers/playerSlice"; import { playerStore } from "@/stores";
import { store } from "@/store";
import { playerStore } from "@/valtioStores";
export default function handleHsWatchChange(pb: ygopro.YgoStocMsg) { export default function handleHsWatchChange(pb: ygopro.YgoStocMsg) {
// const dispatch = store.dispatch;
const count = pb.stoc_hs_watch_change.count; const count = pb.stoc_hs_watch_change.count;
// dispatch(observerChange(count));
playerStore.observerCount = count; playerStore.observerCount = count;
} }
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { setJoined } from "@/reducers/joinSlice"; import { joinStore } from "@/stores";
import { store } from "@/store";
import { joinStore } from "@/valtioStores";
export default function handleJoinGame(pb: ygopro.YgoStocMsg) { export default function handleJoinGame(pb: ygopro.YgoStocMsg) {
// const dispatch = store.dispatch;
const msg = pb.stoc_join_game; const msg = pb.stoc_join_game;
// todo // todo
// dispatch(setJoined());
joinStore.value = true; joinStore.value = true;
} }
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { import { playerStore } from "@/stores";
hostChange,
player0Update,
player1Update,
updateIsHost,
} from "@/reducers/playerSlice";
import { store } from "@/store";
import { playerStore } from "@/valtioStores";
const NO_READY_STATE = "not ready"; const NO_READY_STATE = "not ready";
export default function handleTypeChange(pb: ygopro.YgoStocMsg) { export default function handleTypeChange(pb: ygopro.YgoStocMsg) {
// const dispatch = store.dispatch;
const selfType = pb.stoc_type_change.self_type; const selfType = pb.stoc_type_change.self_type;
const assertHost = pb.stoc_type_change.is_host; const assertHost = pb.stoc_type_change.is_host;
// dispatch(updateIsHost(assertHost));
playerStore.isHost = assertHost; playerStore.isHost = assertHost;
if (assertHost) { if (assertHost) {
switch (selfType) { switch (selfType) {
case ygopro.StocTypeChange.SelfType.PLAYER1: { case ygopro.StocTypeChange.SelfType.PLAYER1: {
// dispatch(hostChange(0));
// dispatch(player0Update(NO_READY_STATE));
playerStore.player0.isHost = true; playerStore.player0.isHost = true;
playerStore.player1.isHost = false; playerStore.player1.isHost = false;
playerStore.player0.state = NO_READY_STATE; playerStore.player0.state = NO_READY_STATE;
break; break;
} }
case ygopro.StocTypeChange.SelfType.PLAYER2: { case ygopro.StocTypeChange.SelfType.PLAYER2: {
// dispatch(hostChange(0));
// dispatch(player1Update(NO_READY_STATE));
playerStore.player0.isHost = false; playerStore.player0.isHost = false;
playerStore.player1.isHost = true; playerStore.player1.isHost = true;
playerStore.player1.state = NO_READY_STATE; playerStore.player1.state = NO_READY_STATE;
break; break;
} }
default: { default: {
......
/*
* 全局状态存储模块
* */
import { configureStore, Unsubscribe } from "@reduxjs/toolkit";
import chatReducer from "./reducers/chatSlice";
import duelReducer from "./reducers/duel/mod";
import joinedReducer from "./reducers/joinSlice";
import moraReducer from "./reducers/moraSlice";
import playerReducer from "./reducers/playerSlice";
export const store = configureStore({
reducer: {
join: joinedReducer,
chat: chatReducer,
player: playerReducer,
mora: moraReducer,
duel: duelReducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: ["duel/updateHp", "duel/reloadField"],
},
}),
});
// Ref: https://github.com/reduxjs/redux/issues/303
export function observeStore<T>(
select: (state: RootState) => T,
onChange: (prev: T | null, cur: T) => void
): Unsubscribe {
let currentState: T | null = null;
const changeHook = () => {
const nextState = select(store.getState());
if (nextState !== currentState) {
onChange(currentState, nextState);
currentState = nextState;
}
};
const unsubscribe = store.subscribe(changeHook);
changeHook();
return unsubscribe;
}
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
...@@ -15,7 +15,7 @@ import { messageStore } from "./messageStore"; ...@@ -15,7 +15,7 @@ import { messageStore } from "./messageStore";
import { moraStore } from "./moraStore"; import { moraStore } from "./moraStore";
import { playerStore } from "./playerStore"; import { playerStore } from "./playerStore";
export const valtioStore = proxy({ export const store = proxy({
playerStore, playerStore,
chatStore, chatStore,
joinStore, joinStore,
...@@ -24,4 +24,4 @@ export const valtioStore = proxy({ ...@@ -24,4 +24,4 @@ export const valtioStore = proxy({
messageStore, // 决斗的信息,包括模态框 messageStore, // 决斗的信息,包括模态框
}); });
devtools(valtioStore, { name: "valtio store", enabled: true }); devtools(store, { name: "valtio store", enabled: true });
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { fetchCard, getCardStr } from "@/api/cards"; import { fetchCard, getCardStr } from "@/api/cards";
import { matStore, messageStore } from "@/valtioStores"; import { matStore, messageStore } from "@/stores";
function CardZoneToChinese(zone: ygopro.CardZone): string { function CardZoneToChinese(zone: ygopro.CardZone): string {
switch (zone) { switch (zone) {
......
import type { ygopro } from "@/api"; import type { ygopro } from "@/api";
import { DESCRIPTION_LIMIT, fetchStrings, getStrings } from "@/api";
import { fetchCard } from "@/api/cards"; import { fetchCard } from "@/api/cards";
import { DESCRIPTION_LIMIT, fetchStrings, getStrings } from "@/api/strings";
import { matStore } from "../store"; import { matStore } from "../store";
......
import { fetchCard } from "@/api"; import { fetchCard } from "@/api";
import { matStore } from "@/valtioStores"; import { matStore } from "@/stores";
export const fetchOverlayMeta = async ( export const fetchOverlayMeta = async (
controller: number, controller: number,
......
import type { ygopro } from "@/api"; import type { ygopro } from "@/api";
import { matStore } from "@/valtioStores"; import { matStore } from "@/stores";
export const getCardByLocation = (location: ygopro.CardLocation) => { export const getCardByLocation = (location: ygopro.CardLocation) => {
return matStore.in(location.location).of(location.controler)[ return matStore.in(location.location).of(location.controler)[
......
...@@ -5,7 +5,6 @@ import { ygopro } from "@/api"; ...@@ -5,7 +5,6 @@ import { ygopro } from "@/api";
import { fetchCard } from "@/api/cards"; import { fetchCard } from "@/api/cards";
import type { import type {
BothSide,
CardState, CardState,
DuelFieldState as ArrayCardState, DuelFieldState as ArrayCardState,
InitInfo, InitInfo,
...@@ -34,26 +33,15 @@ class CardArray extends Array<CardState> implements ArrayCardState { ...@@ -34,26 +33,15 @@ class CardArray extends Array<CardState> implements ArrayCardState {
counters: {}, counters: {},
idleInteractivities: [], idleInteractivities: [],
}); });
/** 内部输出一些注释,等稳定了再移除这个log */
private logInside(name: string, obj: Record<string, any>) {
console.warn("matStore", name, {
zone: ygopro.CardZone[this.zone],
controller: getWhom(this.getController()),
...obj,
});
}
// methods // methods
remove(sequence: number) { remove(sequence: number) {
this.logInside("remove", { sequence });
this.splice(sequence, 1); this.splice(sequence, 1);
} }
async insert(sequence: number, id: number) { async insert(sequence: number, id: number) {
this.logInside("insert", { sequence, id });
const card = await this.genCard(this.getController(), id); const card = await this.genCard(this.getController(), id);
this.splice(sequence, 0, card); this.splice(sequence, 0, card);
} }
async add(ids: number[]) { async add(ids: number[]) {
this.logInside("add", { ids });
const cards = await Promise.all( const cards = await Promise.all(
ids.map(async (id) => this.genCard(this.getController(), id)) ids.map(async (id) => this.genCard(this.getController(), id))
); );
...@@ -64,7 +52,6 @@ class CardArray extends Array<CardState> implements ArrayCardState { ...@@ -64,7 +52,6 @@ class CardArray extends Array<CardState> implements ArrayCardState {
id: number, id: number,
position?: ygopro.CardPosition position?: ygopro.CardPosition
) { ) {
this.logInside("setOccupant", { sequence, id, position });
const meta = await fetchCard(id); const meta = await fetchCard(id);
const target = this[sequence]; const target = this[sequence];
target.occupant = meta; target.occupant = meta;
...@@ -76,14 +63,12 @@ class CardArray extends Array<CardState> implements ArrayCardState { ...@@ -76,14 +63,12 @@ class CardArray extends Array<CardState> implements ArrayCardState {
sequence: number, sequence: number,
interactivity: CardState["idleInteractivities"][number] interactivity: CardState["idleInteractivities"][number]
) { ) {
this.logInside("addIdleInteractivity", { sequence, interactivity });
this[sequence].idleInteractivities.push(interactivity); this[sequence].idleInteractivities.push(interactivity);
} }
clearIdleInteractivities() { clearIdleInteractivities() {
this.forEach((card) => (card.idleInteractivities = [])); this.forEach((card) => (card.idleInteractivities = []));
} }
setPlaceInteractivityType(sequence: number, interactType: InteractType) { setPlaceInteractivityType(sequence: number, interactType: InteractType) {
this.logInside("setPlaceInteractivityType", { sequence, interactType });
this[sequence].placeInteractivity = { this[sequence].placeInteractivity = {
interactType: interactType, interactType: interactType,
response: { response: {
...@@ -99,6 +84,7 @@ class CardArray extends Array<CardState> implements ArrayCardState { ...@@ -99,6 +84,7 @@ class CardArray extends Array<CardState> implements ArrayCardState {
} }
const genDuelCardArray = (cardStates: CardState[], zone: ygopro.CardZone) => { const genDuelCardArray = (cardStates: CardState[], zone: ygopro.CardZone) => {
// 为什么不放在构造函数里面,是因为不想改造继承自Array的构造函数
const me = cloneDeep(new CardArray(...cardStates)); const me = cloneDeep(new CardArray(...cardStates));
me.zone = zone; me.zone = zone;
me.getController = () => (matStore.selfType === 1 ? 0 : 1); me.getController = () => (matStore.selfType === 1 ? 0 : 1);
...@@ -239,12 +225,10 @@ export const matStore: MatState = proxy<MatState>({ ...@@ -239,12 +225,10 @@ export const matStore: MatState = proxy<MatState>({
isMe, isMe,
}); });
// 以后再来解决这些... // @ts-ignore 挂到全局,便于调试
// @ts-ignore
window.matStore = matStore; window.matStore = matStore;
// 修改原型链,因为valtiol的proxy会把原型链改掉。这应该是valtio的一个bug...有空提issue去改 // 修改原型链,因为valtio的proxy会把原型链改掉。这应该是valtio的一个bug...有空提issue去改
(["me", "op"] as const).forEach((who) => { (["me", "op"] as const).forEach((who) => {
( (
[ [
......
import { matStore } from "@/valtioStores"; import { matStore } from "@/stores";
export const clearAllIdleInteractivities = (controller: number) => { export const clearAllIdleInteractivities = (controller: number) => {
matStore.banishedZones.of(controller).clearIdleInteractivities(); matStore.banishedZones.of(controller).clearIdleInteractivities();
......
import { matStore } from "@/valtioStores";
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { matStore } from "@/stores";
/** 清空所有place互动性,也可以删除某一个zone的互动性。zone为空则为清除所有。 */ /** 清空所有place互动性,也可以删除某一个zone的互动性。zone为空则为清除所有。 */
export const clearAllPlaceInteradtivities = ( export const clearAllPlaceInteradtivities = (
......
import { fetchCard, type ygopro } from "@/api"; import { fetchCard, type ygopro } from "@/api";
import { getCardByLocation, messageStore } from "@/valtioStores"; import { getCardByLocation, messageStore } from "@/stores";
export const fetchCheckCardMetasV2 = async ({ export const fetchCheckCardMetasV2 = async ({
selected, selected,
......
import { fetchCard, type ygopro } from "@/api"; import { fetchCard, type ygopro } from "@/api";
import { getCardByLocation, messageStore } from "@/valtioStores"; import { getCardByLocation, messageStore } from "@/stores";
export const fetchCheckCardMetasV3 = async ({ export const fetchCheckCardMetasV3 = async ({
mustSelect, mustSelect,
......
export * from "./clearAllIdleInteractivities"; export * from "./clearAllIdleInteractivities";
export * from "./clearAllPlaceInteradtivities";
export * from "./fetchCheckCardMetasV2"; export * from "./fetchCheckCardMetasV2";
export * from "./fetchCheckCardMetasV3"; export * from "./fetchCheckCardMetasV3";
export * from "./clearAllPlaceInteradtivities";
...@@ -2,7 +2,6 @@ import * as BABYLON from "@babylonjs/core"; ...@@ -2,7 +2,6 @@ import * as BABYLON from "@babylonjs/core";
import { Row } from "antd"; import { Row } from "antd";
import React from "react"; import React from "react";
import { Engine, Scene } from "react-babylonjs"; import { Engine, Scene } from "react-babylonjs";
import { Provider, ReactReduxContext } from "react-redux";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
...@@ -75,11 +74,8 @@ const NeosSider = () => ( ...@@ -75,11 +74,8 @@ const NeosSider = () => (
); );
const NeosCanvas = () => ( const NeosCanvas = () => (
<ReactReduxContext.Consumer>
{({ store }) => (
<Engine antialias adaptToDeviceRatio canvasId="babylonJS"> <Engine antialias adaptToDeviceRatio canvasId="babylonJS">
<Scene> <Scene>
<Provider store={store}>
<Camera /> <Camera />
<Light /> <Light />
<Hands /> <Hands />
...@@ -92,11 +88,8 @@ const NeosCanvas = () => ( ...@@ -92,11 +88,8 @@ const NeosCanvas = () => (
<BanishedZone /> <BanishedZone />
<Field /> <Field />
<Ground /> <Ground />
</Provider>
</Scene> </Scene>
</Engine> </Engine>
)}
</ReactReduxContext.Consumer>
); );
const Camera = () => ( const Camera = () => (
......
import { Alert as AntdAlert } from "antd"; import { Alert as AntdAlert } from "antd";
import React from "react"; import React from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { sendSurrender } from "@/api/ocgcore/ocgHelper";
import { useAppSelector } from "@/hook";
import { selectUnimplemented } from "@/reducers/duel/mod";
import { matStore } from "@/valtioStores";
import { useSnapshot } from "valtio"; import { useSnapshot } from "valtio";
export const Alert = () => { import { sendSurrender } from "@/api";
// const unimplemented = useAppSelector(selectUnimplemented); import { matStore } from "@/stores";
export const Alert = () => {
const matSnap = useSnapshot(matStore); const matSnap = useSnapshot(matStore);
const unimplemented = matSnap.unimplemented; const unimplemented = matSnap.unimplemented;
......
import { Button, Drawer, List } from "antd"; import { Button, Drawer, List } from "antd";
import React from "react"; import React from "react";
import { useSnapshot } from "valtio";
import { sendSelectIdleCmdResponse } from "@/api/ocgcore/ocgHelper"; import { sendSelectIdleCmdResponse } from "@/api";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook";
import {
clearAllIdleInteractivities,
setCardListModalIsOpen,
} from "@/reducers/duel/mod";
import {
selectCardListModalInfo,
selectCardListModalIsOpen,
} from "@/reducers/duel/modal/mod";
import { store } from "@/store";
import { import {
clearAllIdleInteractivities as clearAllIdleInteractivities,
messageStore, messageStore,
matStore, } from "@/stores";
clearAllIdleInteractivities as FIXME_clearAllIdleInteractivities,
} from "@/valtioStores";
import { useSnapshot } from "valtio";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
...@@ -28,16 +16,11 @@ const CARD_WIDTH = 100; ...@@ -28,16 +16,11 @@ const CARD_WIDTH = 100;
const { cardListModal } = messageStore; const { cardListModal } = messageStore;
export const CardListModal = () => { export const CardListModal = () => {
// const dispatch = store.dispatch;
// const isOpen = useAppSelector(selectCardListModalIsOpen);
// const list = useAppSelector(selectCardListModalInfo);
const snapCardListModal = useSnapshot(cardListModal); const snapCardListModal = useSnapshot(cardListModal);
const isOpen = snapCardListModal.isOpen; const isOpen = snapCardListModal.isOpen;
const list = snapCardListModal.list as typeof cardListModal.list; const list = snapCardListModal.list as typeof cardListModal.list;
const handleOkOrCancel = () => { const handleOkOrCancel = () => {
// dispatch(setCardListModalIsOpen(false));
cardListModal.isOpen = false; cardListModal.isOpen = false;
}; };
...@@ -53,13 +36,9 @@ export const CardListModal = () => { ...@@ -53,13 +36,9 @@ export const CardListModal = () => {
key={idx} key={idx}
onClick={() => { onClick={() => {
sendSelectIdleCmdResponse(interactivy.response); sendSelectIdleCmdResponse(interactivy.response);
// dispatch(setCardListModalIsOpen(false));
// dispatch(clearAllIdleInteractivities(0));
// dispatch(clearAllIdleInteractivities(1));
cardListModal.isOpen = false; cardListModal.isOpen = false;
FIXME_clearAllIdleInteractivities(0); clearAllIdleInteractivities(0);
FIXME_clearAllIdleInteractivities(1); clearAllIdleInteractivities(1);
}} }}
> >
{interactivy.desc} {interactivy.desc}
......
...@@ -3,22 +3,14 @@ import { Button, Card, Col, Modal, Row } from "antd"; ...@@ -3,22 +3,14 @@ import { Button, Card, Col, Modal, Row } from "antd";
import { ReactComponent as BattleSvg } from "neos-assets/battle-axe.svg"; import { ReactComponent as BattleSvg } from "neos-assets/battle-axe.svg";
import { ReactComponent as DefenceSvg } from "neos-assets/checked-shield.svg"; import { ReactComponent as DefenceSvg } from "neos-assets/checked-shield.svg";
import React from "react"; import React from "react";
import { useSnapshot } from "valtio";
import { sendSelectIdleCmdResponse } from "@/api/ocgcore/ocgHelper"; import { fetchStrings, sendSelectIdleCmdResponse } from "@/api";
import { fetchStrings } from "@/api/strings";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook";
import {
clearAllIdleInteractivities,
setCardModalIsOpen,
} from "@/reducers/duel/mod";
import { import {
selectCardModalCounters, clearAllIdleInteractivities as clearAllIdleInteractivities,
selectCardModalInteractivies, messageStore,
selectCardModalIsOpen, } from "@/stores";
selectCardModalMeta,
} from "@/reducers/duel/modal/mod";
import { store } from "@/store";
import { import {
Attribute2StringCodeMap, Attribute2StringCodeMap,
...@@ -27,12 +19,6 @@ import { ...@@ -27,12 +19,6 @@ import {
Type2StringCodeMap, Type2StringCodeMap,
} from "../../../common"; } from "../../../common";
import {
messageStore,
clearAllIdleInteractivities as FIXME_clearAllIdleInteractivities,
} from "@/valtioStores";
import { useSnapshot } from "valtio";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
const { Meta } = Card; const { Meta } = Card;
const CARD_WIDTH = 240; const CARD_WIDTH = 240;
...@@ -64,11 +50,9 @@ export const CardModal = () => { ...@@ -64,11 +50,9 @@ export const CardModal = () => {
const imgUrl = meta?.id const imgUrl = meta?.id
? `${NeosConfig.cardImgUrl}/${meta.id}.jpg` ? `${NeosConfig.cardImgUrl}/${meta.id}.jpg`
: undefined; : undefined;
// const interactivies = useAppSelector(selectCardModalInteractivies);
const interactivies = snapCardModal.interactivies; const interactivies = snapCardModal.interactivies;
const handleOkOrCancel = () => { const handleOkOrCancel = () => {
// dispatch(setCardModalIsOpen(false));
cardModal.isOpen = false; cardModal.isOpen = false;
}; };
...@@ -95,12 +79,9 @@ export const CardModal = () => { ...@@ -95,12 +79,9 @@ export const CardModal = () => {
key={idx} key={idx}
onClick={() => { onClick={() => {
sendSelectIdleCmdResponse(interactive.response); sendSelectIdleCmdResponse(interactive.response);
// dispatch(setCardModalIsOpen(false));
// dispatch(clearAllIdleInteractivities(0));
// dispatch(clearAllIdleInteractivities(1));
cardModal.isOpen = false; cardModal.isOpen = false;
FIXME_clearAllIdleInteractivities(0); clearAllIdleInteractivities(0);
FIXME_clearAllIdleInteractivities(1); clearAllIdleInteractivities(1);
}} }}
> >
{interactive.desc} {interactive.desc}
......
...@@ -2,48 +2,20 @@ import { ThunderboltOutlined } from "@ant-design/icons"; ...@@ -2,48 +2,20 @@ import { ThunderboltOutlined } from "@ant-design/icons";
import { CheckCard, CheckCardProps } from "@ant-design/pro-components"; import { CheckCard, CheckCardProps } from "@ant-design/pro-components";
import { Button, Col, Popover, Row } from "antd"; import { Button, Col, Popover, Row } from "antd";
import React, { useState } from "react"; import React, { useState } from "react";
import { useSnapshot } from "valtio";
import { import { sendSelectCardResponse, sendSelectChainResponse } from "@/api";
sendSelectCardResponse,
sendSelectChainResponse,
} from "@/api/ocgcore/ocgHelper";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook"; import { matStore, messageStore } from "@/stores";
import { selectHint } from "@/reducers/duel/hintSlice";
import {
resetCheckCardModal,
setCheckCardModalIsOpen,
} from "@/reducers/duel/mod";
import {
selectCheckCardModalCacnelResponse,
selectCheckCardModalCancelAble,
selectCheckCardModalIsOpen,
selectCheckCardModalMinMax,
selectCheckCardModalOnSubmit,
selectCheckCardModalTags,
} from "@/reducers/duel/modal/mod";
import { store } from "@/store";
import { DragModal } from "./DragModal"; import { DragModal } from "./DragModal";
import { messageStore, matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
const { checkCardModal } = messageStore; const { checkCardModal } = messageStore;
export const CheckCardModal = () => { export const CheckCardModal = () => {
const snapCheckCardModal = useSnapshot(checkCardModal); const snapCheckCardModal = useSnapshot(checkCardModal);
// const dispatch = store.dispatch;
// const isOpen = useAppSelector(selectCheckCardModalIsOpen);
// const { min, max } = useAppSelector(selectCheckCardModalMinMax);
// const tabs = useAppSelector(selectCheckCardModalTags);
// const onSubmit = useAppSelector(selectCheckCardModalOnSubmit);
// const cancelAble = useAppSelector(selectCheckCardModalCancelAble);
// const cancelResponse = useAppSelector(selectCheckCardModalCacnelResponse);
const isOpen = snapCheckCardModal.isOpen; const isOpen = snapCheckCardModal.isOpen;
const min = snapCheckCardModal.selectMin ?? 0; const min = snapCheckCardModal.selectMin ?? 0;
const max = snapCheckCardModal.selectMax ?? 10; const max = snapCheckCardModal.selectMax ?? 10;
...@@ -54,7 +26,6 @@ export const CheckCardModal = () => { ...@@ -54,7 +26,6 @@ export const CheckCardModal = () => {
const [response, setResponse] = useState<number[]>([]); const [response, setResponse] = useState<number[]>([]);
const defaultValue: number[] = []; const defaultValue: number[] = [];
// const hint = useAppSelector(selectHint);
const hint = useSnapshot(matStore.hint); const hint = useSnapshot(matStore.hint);
const preHintMsg = hint?.esHint || ""; const preHintMsg = hint?.esHint || "";
const selectHintMsg = hint?.esSelectHint || "请选择卡片"; const selectHintMsg = hint?.esSelectHint || "请选择卡片";
...@@ -78,13 +49,7 @@ export const CheckCardModal = () => { ...@@ -78,13 +49,7 @@ export const CheckCardModal = () => {
} }
}; };
const FIXME_resetCheckCardModal = () => { const resetCheckCardModal = () => {
// state.modalState.checkCardModal.isOpen = false;
// state.modalState.checkCardModal.selectMin = undefined;
// state.modalState.checkCardModal.selectMax = undefined;
// state.modalState.checkCardModal.cancelAble = false;
// state.modalState.checkCardModal.cancelResponse = undefined;
// state.modalState.checkCardModal.tags = [];
checkCardModal.isOpen = false; checkCardModal.isOpen = false;
checkCardModal.selectMin = undefined; checkCardModal.selectMin = undefined;
checkCardModal.selectMax = undefined; checkCardModal.selectMax = undefined;
...@@ -104,10 +69,8 @@ export const CheckCardModal = () => { ...@@ -104,10 +69,8 @@ export const CheckCardModal = () => {
disabled={response.length < min || response.length > max} disabled={response.length < min || response.length > max}
onClick={() => { onClick={() => {
sendResponseHandler(onSubmit, response); sendResponseHandler(onSubmit, response);
// dispatch(setCheckCardModalIsOpen(false));
// dispatch(resetCheckCardModal());
checkCardModal.isOpen = false; checkCardModal.isOpen = false;
FIXME_resetCheckCardModal(); resetCheckCardModal();
}} }}
onFocus={() => {}} onFocus={() => {}}
onBlur={() => {}} onBlur={() => {}}
...@@ -120,10 +83,8 @@ export const CheckCardModal = () => { ...@@ -120,10 +83,8 @@ export const CheckCardModal = () => {
if (cancelResponse) { if (cancelResponse) {
sendResponseHandler(onSubmit, [cancelResponse]); sendResponseHandler(onSubmit, [cancelResponse]);
} }
// dispatch(setCheckCardModalIsOpen(false));
// dispatch(resetCheckCardModal());
checkCardModal.isOpen = false; checkCardModal.isOpen = false;
FIXME_resetCheckCardModal(); resetCheckCardModal();
}} }}
onFocus={() => {}} onFocus={() => {}}
onBlur={() => {}} onBlur={() => {}}
......
import { CheckCard } from "@ant-design/pro-components"; import { CheckCard } from "@ant-design/pro-components";
import { Button, Card, Col, Row } from "antd"; import { Button, Card, Col, Row } from "antd";
import React from "react"; import React from "react";
import { useSnapshot } from "valtio";
import { sendSelectUnselectCardResponse } from "@/api/ocgcore/ocgHelper"; import { sendSelectUnselectCardResponse } from "@/api";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook"; import { matStore, messageStore } from "@/stores";
import { selectHint } from "@/reducers/duel/hintSlice";
import {
resetCheckCardModalV2,
setCheckCardModalV2IsOpen,
setCheckCardModalV2ResponseAble,
} from "@/reducers/duel/mod";
import {
selectCheckCardModalV2CancelAble,
selectCheckCardModalV2FinishAble,
selectCheckCardModalV2IsOpen,
selectCheckCardModalV2MinMax,
selectCheckCardModalV2ResponseAble,
selectCheckCardModalV2SelectAbleOptions,
selectCheckCardModalV2SelectedOptions,
} from "@/reducers/duel/modal/checkCardModalV2Slice";
import { store } from "@/store";
import { DragModal } from "./DragModal"; import { DragModal } from "./DragModal";
import { messageStore, matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const { checkCardModalV2 } = messageStore; const { checkCardModalV2 } = messageStore;
const NeosConfig = useConfig(); const NeosConfig = useConfig();
export const CheckCardModalV2 = () => { export const CheckCardModalV2 = () => {
const snapCheckCardModalV2 = useSnapshot(checkCardModalV2); const snapCheckCardModalV2 = useSnapshot(checkCardModalV2);
// const dispatch = store.dispatch;
// const isOpen = useAppSelector(selectCheckCardModalV2IsOpen);
// const { min, max } = useAppSelector(selectCheckCardModalV2MinMax);
// const cancelable = useAppSelector(selectCheckCardModalV2CancelAble);
// const finishable = useAppSelector(selectCheckCardModalV2FinishAble);
// const selectableOptions = useAppSelector(
// selectCheckCardModalV2SelectAbleOptions
// );
// const selectedOptions = useAppSelector(selectCheckCardModalV2SelectedOptions);
// const responseable = useAppSelector(selectCheckCardModalV2ResponseAble);
// const hint = useAppSelector(selectHint);
const isOpen = snapCheckCardModalV2.isOpen; const isOpen = snapCheckCardModalV2.isOpen;
const min = snapCheckCardModalV2.selectMin ?? 0; const min = snapCheckCardModalV2.selectMin ?? 0;
...@@ -57,13 +28,7 @@ export const CheckCardModalV2 = () => { ...@@ -57,13 +28,7 @@ export const CheckCardModalV2 = () => {
const preHintMsg = hint?.esHint || ""; const preHintMsg = hint?.esHint || "";
const selectHintMsg = hint?.esSelectHint || "请选择卡片"; const selectHintMsg = hint?.esSelectHint || "请选择卡片";
const FIXME_resetCheckCardModalV2 = () => { const resetCheckCardModalV2 = () => {
// modalState.isOpen = false;
// modalState.finishAble = false;
// modalState.cancelAble = false;
// modalState.responseable = false;
// modalState.selectableOptions = [];
// modalState.selectedOptions = [];
checkCardModalV2.isOpen = false; checkCardModalV2.isOpen = false;
checkCardModalV2.finishAble = false; checkCardModalV2.finishAble = false;
checkCardModalV2.cancelAble = false; checkCardModalV2.cancelAble = false;
...@@ -73,13 +38,10 @@ export const CheckCardModalV2 = () => { ...@@ -73,13 +38,10 @@ export const CheckCardModalV2 = () => {
}; };
const onFinishOrCancel = () => { const onFinishOrCancel = () => {
sendSelectUnselectCardResponse({ cancel_or_finish: true }); sendSelectUnselectCardResponse({ cancel_or_finish: true });
// dispatch(setCheckCardModalV2IsOpen(false));
// dispatch(resetCheckCardModalV2());
// dispatch(setCheckCardModalV2ResponseAble(false));
checkCardModalV2.isOpen = false; checkCardModalV2.isOpen = false;
checkCardModalV2.responseable = false; checkCardModalV2.responseable = false;
FIXME_resetCheckCardModalV2(); resetCheckCardModalV2();
}; };
return ( return (
...@@ -110,10 +72,8 @@ export const CheckCardModalV2 = () => { ...@@ -110,10 +72,8 @@ export const CheckCardModalV2 = () => {
size="small" size="small"
onChange={(value) => { onChange={(value) => {
if (responseable) { if (responseable) {
// dispatch(setCheckCardModalV2IsOpen(false));
// @ts-ignore // @ts-ignore
sendSelectUnselectCardResponse({ selected_ptr: value }); sendSelectUnselectCardResponse({ selected_ptr: value });
// dispatch(setCheckCardModalV2ResponseAble(false));
checkCardModalV2.isOpen = false; checkCardModalV2.isOpen = false;
checkCardModalV2.responseable = false; checkCardModalV2.responseable = false;
} }
......
import { CheckCard } from "@ant-design/pro-components"; import { CheckCard } from "@ant-design/pro-components";
import { Button, Card, Col, Row } from "antd"; import { Button, Card, Col, Row } from "antd";
import React, { useState } from "react"; import React, { useState } from "react";
import { useSnapshot } from "valtio";
import { sendSelectCardResponse } from "@/api/ocgcore/ocgHelper"; import { sendSelectCardResponse } from "@/api";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook"; import { matStore, messageStore } from "@/stores";
import { selectHint } from "@/reducers/duel/hintSlice";
import {
resetCheckCardModalV3,
setCheckCardModalV3IsOpen,
setCheckCardModalV3ResponseAble,
} from "@/reducers/duel/mod";
import { selectCheckCardModalV3 } from "@/reducers/duel/modal/checkCardModalV3Slice";
import { store } from "@/store";
import { DragModal } from "./DragModal"; import { DragModal } from "./DragModal";
import { messageStore, matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
const { checkCardModalV3 } = messageStore; const { checkCardModalV3 } = messageStore;
...@@ -26,17 +16,6 @@ const { checkCardModalV3 } = messageStore; ...@@ -26,17 +16,6 @@ const { checkCardModalV3 } = messageStore;
export const CheckCardModalV3 = () => { export const CheckCardModalV3 = () => {
const snapCheckCardModalV3 = useSnapshot(checkCardModalV3); const snapCheckCardModalV3 = useSnapshot(checkCardModalV3);
// const dispatch = store.dispatch;
// const state = useAppSelector(selectCheckCardModalV3);
// const isOpen = state.isOpen;
// const min = state.selectMin || 0;
// const max = state.selectMax || 0;
// const mustSelectOptions = state.mustSelectList;
// const selectAbleOptions = state.selectAbleList;
// const overflow = state.overflow;
// const LevelSum = state.allLevel;
const isOpen = snapCheckCardModalV3.isOpen; const isOpen = snapCheckCardModalV3.isOpen;
const min = snapCheckCardModalV3.selectMin || 0; const min = snapCheckCardModalV3.selectMin || 0;
const max = snapCheckCardModalV3.selectMax || 0; const max = snapCheckCardModalV3.selectMax || 0;
...@@ -54,7 +33,6 @@ export const CheckCardModalV3 = () => { ...@@ -54,7 +33,6 @@ export const CheckCardModalV3 = () => {
.concat(selectedOptions) .concat(selectedOptions)
.map((option) => option.level2) .map((option) => option.level2)
.reduce((sum, current) => sum + current, 0); .reduce((sum, current) => sum + current, 0);
// const hint = useAppSelector(selectHint);
const hint = useSnapshot(matStore.hint); const hint = useSnapshot(matStore.hint);
const preHintMsg = hint?.esHint || ""; const preHintMsg = hint?.esHint || "";
const selectHintMsg = hint?.esSelectHint || "请选择卡片"; const selectHintMsg = hint?.esSelectHint || "请选择卡片";
...@@ -69,24 +47,12 @@ export const CheckCardModalV3 = () => { ...@@ -69,24 +47,12 @@ export const CheckCardModalV3 = () => {
sendSelectCardResponse( sendSelectCardResponse(
mustSelectOptions.concat(selectedOptions).map((option) => option.response) mustSelectOptions.concat(selectedOptions).map((option) => option.response)
); );
// dispatch(setCheckCardModalV3IsOpen(false));
// dispatch(resetCheckCardModalV3());
// dispatch(setCheckCardModalV3ResponseAble(false));
checkCardModalV3.isOpen = false; checkCardModalV3.isOpen = false;
checkCardModalV3.responseable = false; checkCardModalV3.responseable = false;
checkCardModalV3.overflow = false; checkCardModalV3.overflow = false;
checkCardModalV3.allLevel = 0; checkCardModalV3.allLevel = 0;
checkCardModalV3.mustSelectList = []; checkCardModalV3.mustSelectList = [];
checkCardModalV3.selectAbleList = []; checkCardModalV3.selectAbleList = [];
// 下面就是resetCheckCardModalV3的内容
// modalState.isOpen = false;
// modalState.overflow = false;
// modalState.allLevel = 0;
// modalState.responseable = undefined;
// modalState.mustSelectList = [];
// modalState.selectAbleList = [];
}; };
return ( return (
......
import { Button, Card, Col, InputNumber, Row } from "antd"; import { Button, Card, Col, InputNumber, Row } from "antd";
import React, { useState } from "react"; import React, { useState } from "react";
import { useSnapshot } from "valtio";
import { sendSelectCounterResponse } from "@/api/ocgcore/ocgHelper"; import { fetchStrings, sendSelectCounterResponse } from "@/api";
import { fetchStrings } from "@/api/strings";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook"; import { messageStore } from "@/stores";
import { clearCheckCounter } from "@/reducers/duel/mod";
import { selectCheckCounterModal } from "@/reducers/duel/modal/checkCounterModalSlice";
import { store } from "@/store";
import { DragModal } from "./DragModal"; import { DragModal } from "./DragModal";
import { messageStore, matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const { checkCounterModal } = messageStore; const { checkCounterModal } = messageStore;
const NeosConfig = useConfig(); const NeosConfig = useConfig();
export const CheckCounterModal = () => { export const CheckCounterModal = () => {
const snapCheckCounterModal = useSnapshot(checkCounterModal); const snapCheckCounterModal = useSnapshot(checkCounterModal);
const snapMat = useSnapshot(matStore);
// const dispatch = store.dispatch;
// const state = useAppSelector(selectCheckCounterModal);
// const isOpen = state.isOpen;
// const counterName = fetchStrings("!counter", `0x${state.counterType!}`);
// const min = state.min || 0;
// const options = state.options;
const isOpen = snapCheckCounterModal.isOpen; const isOpen = snapCheckCounterModal.isOpen;
const min = snapCheckCounterModal.min || 0; const min = snapCheckCounterModal.min || 0;
...@@ -42,7 +28,6 @@ export const CheckCounterModal = () => { ...@@ -42,7 +28,6 @@ export const CheckCounterModal = () => {
const onFinish = () => { const onFinish = () => {
sendSelectCounterResponse(selected); sendSelectCounterResponse(selected);
// dispatch(clearCheckCounter());
messageStore.checkCounterModal.isOpen = false; messageStore.checkCounterModal.isOpen = false;
messageStore.checkCounterModal.min = undefined; messageStore.checkCounterModal.min = undefined;
messageStore.checkCounterModal.counterType = undefined; messageStore.checkCounterModal.counterType = undefined;
......
import { notification } from "antd"; import { notification } from "antd";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useSnapshot } from "valtio";
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { useAppSelector } from "@/hook";
import { selectHint } from "@/reducers/duel/hintSlice";
import { selectDuelResult, selectWaiting } from "@/reducers/duel/mod";
import { selectCurrentPhase } from "@/reducers/duel/phaseSlice";
import MsgWin = ygopro.StocGameMessage.MsgWin;
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { matStore } from "@/stores";
import { matStore } from "@/valtioStores"; const MsgWin = ygopro.StocGameMessage.MsgWin;
import { useSnapshot } from "valtio";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
export const HintNotification = () => { export const HintNotification = () => {
// const hint = useAppSelector(selectHint); const hintState = matStore.hint;
const hint = useSnapshot(matStore.hint); const hintSnap = useSnapshot(matStore.hint);
const currentPhase = useAppSelector(selectCurrentPhase);
const waiting = useAppSelector(selectWaiting); const currentPhase = matStore.phase.currentPhase;
const result = useAppSelector(selectDuelResult); const waiting = matStore.waiting;
const result = matStore.result;
const navigate = useNavigate(); const navigate = useNavigate();
const [api, contextHolder] = notification.useNotification({ const [api, contextHolder] = notification.useNotification({
maxCount: NeosConfig.ui.hint.maxCount, maxCount: NeosConfig.ui.hint.maxCount,
}); });
useEffect(() => { useEffect(() => {
if (hint && hint.msg) { if (hintState && hintState.msg) {
api.info({ api.info({
message: `${hint.msg}`, message: `${hintState.msg}`,
placement: "bottom", placement: "bottom",
}); });
} }
}, [hint?.msg]); }, [hintSnap?.msg]);
useEffect(() => { useEffect(() => {
if (currentPhase) { if (currentPhase) {
......
import { CheckCard } from "@ant-design/pro-components"; import { CheckCard } from "@ant-design/pro-components";
import { Button } from "antd"; import { Button } from "antd";
import React, { useState } from "react"; import React, { useState } from "react";
import { useSnapshot } from "valtio";
import { sendSelectOptionResponse } from "@/api/ocgcore/ocgHelper"; import { sendSelectOptionResponse } from "@/api";
import { useAppSelector } from "@/hook"; import { messageStore } from "@/stores";
import { resetOptionModal, setOptionModalIsOpen } from "@/reducers/duel/mod";
import {
selectOptionModalIsOpen,
selectOptionModalOptions,
} from "@/reducers/duel/modal/mod";
import { store } from "@/store";
import { DragModal } from "./DragModal"; import { DragModal } from "./DragModal";
import { messageStore, matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const { optionModal } = messageStore; const { optionModal } = messageStore;
export const OptionModal = () => { export const OptionModal = () => {
// const dispatch = store.dispatch;
// const isOpen = useAppSelector(selectOptionModalIsOpen);
// const options = useAppSelector(selectOptionModalOptions);
const snapOptionModal = useSnapshot(optionModal); const snapOptionModal = useSnapshot(optionModal);
const isOpen = snapOptionModal.isOpen; const isOpen = snapOptionModal.isOpen;
...@@ -40,8 +29,6 @@ export const OptionModal = () => { ...@@ -40,8 +29,6 @@ export const OptionModal = () => {
onClick={() => { onClick={() => {
if (selected !== undefined) { if (selected !== undefined) {
sendSelectOptionResponse(selected); sendSelectOptionResponse(selected);
// dispatch(setOptionModalIsOpen(false));
// dispatch(resetOptionModal());
optionModal.isOpen = false; optionModal.isOpen = false;
optionModal.options = []; optionModal.options = [];
} }
......
...@@ -5,33 +5,17 @@ import { ReactComponent as EpSvg } from "neos-assets/power-button.svg"; ...@@ -5,33 +5,17 @@ import { ReactComponent as EpSvg } from "neos-assets/power-button.svg";
import { ReactComponent as Main2Svg } from "neos-assets/sword-in-stone.svg"; import { ReactComponent as Main2Svg } from "neos-assets/sword-in-stone.svg";
import { ReactComponent as SurrenderSvg } from "neos-assets/truce.svg"; import { ReactComponent as SurrenderSvg } from "neos-assets/truce.svg";
import React, { useState } from "react"; import React, { useState } from "react";
import { useSnapshot } from "valtio";
import { import {
sendSelectBattleCmdResponse, sendSelectBattleCmdResponse,
sendSelectIdleCmdResponse, sendSelectIdleCmdResponse,
sendSurrender, sendSurrender,
} from "@/api/ocgcore/ocgHelper"; } from "@/api";
import { useAppSelector } from "@/hook";
import {
clearAllIdleInteractivities,
setEnableBp,
setEnableEp,
setEnableM2,
} from "@/reducers/duel/mod";
import { import {
selectCurrentPhase, clearAllIdleInteractivities as clearAllIdleInteractivities,
selectEnableBp,
selectEnableEp,
selectEnableM2,
} from "@/reducers/duel/phaseSlice";
import { store } from "@/store";
import {
messageStore,
matStore, matStore,
clearAllIdleInteractivities as FIXME_clearAllIdleInteractivities, } from "@/stores";
} from "@/valtioStores";
import { useSnapshot } from "valtio";
const IconSize = "150%"; const IconSize = "150%";
const SpaceSize = 16; const SpaceSize = 16;
...@@ -57,12 +41,6 @@ const PhaseButton = (props: { ...@@ -57,12 +41,6 @@ const PhaseButton = (props: {
const { phase } = matStore; const { phase } = matStore;
export const Phase = () => { export const Phase = () => {
// const dispatch = store.dispatch;
// const enableBp = useAppSelector(selectEnableBp);
// const enableM2 = useAppSelector(selectEnableM2);
// const enableEp = useAppSelector(selectEnableEp);
// const currentPhase = useAppSelector(selectCurrentPhase);
const snapPhase = useSnapshot(phase); const snapPhase = useSnapshot(phase);
const enableBp = snapPhase.enableBp; const enableBp = snapPhase.enableBp;
const enableM2 = snapPhase.enableM2; const enableM2 = snapPhase.enableM2;
...@@ -81,33 +59,21 @@ export const Phase = () => { ...@@ -81,33 +59,21 @@ export const Phase = () => {
: 7; : 7;
const onBp = () => { const onBp = () => {
// dispatch(clearAllIdleInteractivities(0));
// dispatch(clearAllIdleInteractivities(0));
sendSelectIdleCmdResponse(6); sendSelectIdleCmdResponse(6);
// dispatch(setEnableBp(false)); clearAllIdleInteractivities(0); // 为什么要clear两次?
FIXME_clearAllIdleInteractivities(0); // 为什么要clear两次? clearAllIdleInteractivities(0);
FIXME_clearAllIdleInteractivities(0);
phase.enableBp = false; phase.enableBp = false;
}; };
const onM2 = () => { const onM2 = () => {
// dispatch(clearAllIdleInteractivities(0));
// dispatch(clearAllIdleInteractivities(0));
sendSelectBattleCmdResponse(2); sendSelectBattleCmdResponse(2);
// dispatch(setEnableM2(false)); clearAllIdleInteractivities(0);
FIXME_clearAllIdleInteractivities(0); clearAllIdleInteractivities(0);
FIXME_clearAllIdleInteractivities(0);
phase.enableM2 = false; phase.enableM2 = false;
}; };
const onEp = () => { const onEp = () => {
// dispatch(clearAllIdleInteractivities(0));
// dispatch(clearAllIdleInteractivities(0));
sendSelectIdleCmdResponse(response); sendSelectIdleCmdResponse(response);
// dispatch(setEnableEp(false)); clearAllIdleInteractivities(0);
FIXME_clearAllIdleInteractivities(0); clearAllIdleInteractivities(0);
FIXME_clearAllIdleInteractivities(0);
phase.enableEp = false; phase.enableEp = false;
}; };
const onSurrender = () => { const onSurrender = () => {
......
import { CheckCard } from "@ant-design/pro-components"; import { CheckCard } from "@ant-design/pro-components";
import { Button } from "antd"; import { Button } from "antd";
import React, { useState } from "react"; import React, { useState } from "react";
import { useSnapshot } from "valtio";
import { ygopro } from "@/api"; import { sendSelectPositionResponse, ygopro } from "@/api";
import { sendSelectPositionResponse } from "@/api/ocgcore/ocgHelper"; import { messageStore } from "@/stores";
import { useAppSelector } from "@/hook";
import {
resetPositionModal,
setPositionModalIsOpen,
} from "@/reducers/duel/mod";
import {
selectPositionModalIsOpen,
selectPositionModalPositions,
} from "@/reducers/duel/modal/mod";
import { store } from "@/store";
import { DragModal } from "./DragModal"; import { DragModal } from "./DragModal";
import { messageStore, matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const { positionModal } = messageStore; const { positionModal } = messageStore;
export const PositionModal = () => { export const PositionModal = () => {
// const dispatch = store.dispatch;
const snapPositionModal = useSnapshot(positionModal); const snapPositionModal = useSnapshot(positionModal);
// const isOpen = useAppSelector(selectPositionModalIsOpen);
// const positions = useAppSelector(selectPositionModalPositions);
const isOpen = snapPositionModal.isOpen; const isOpen = snapPositionModal.isOpen;
const positions = snapPositionModal.positions; const positions = snapPositionModal.positions;
...@@ -45,8 +30,6 @@ export const PositionModal = () => { ...@@ -45,8 +30,6 @@ export const PositionModal = () => {
onClick={() => { onClick={() => {
if (selected !== undefined) { if (selected !== undefined) {
sendSelectPositionResponse(selected); sendSelectPositionResponse(selected);
// dispatch(setPositionModalIsOpen(false));
// dispatch(resetPositionModal());
positionModal.isOpen = false; positionModal.isOpen = false;
positionModal.positions = []; positionModal.positions = [];
} }
......
...@@ -2,7 +2,7 @@ import { SendOutlined } from "@ant-design/icons"; ...@@ -2,7 +2,7 @@ import { SendOutlined } from "@ant-design/icons";
import { Button, Col, Input, Row } from "antd"; import { Button, Col, Input, Row } from "antd";
import React, { useState } from "react"; import React, { useState } from "react";
import { sendChat } from "@/api/ocgcore/ocgHelper"; import { sendChat } from "@/api";
export const SendBox = () => { export const SendBox = () => {
const [content, setContent] = useState(""); const [content, setContent] = useState("");
......
...@@ -17,29 +17,19 @@ import { ...@@ -17,29 +17,19 @@ import {
import { CSS } from "@dnd-kit/utilities"; import { CSS } from "@dnd-kit/utilities";
import { Button, Card, Modal } from "antd"; import { Button, Card, Modal } from "antd";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useSnapshot } from "valtio";
import { sendSortCardResponse } from "@/api";
import { CardMeta } from "@/api/cards"; import { CardMeta } from "@/api/cards";
import { sendSortCardResponse } from "@/api/ocgcore/ocgHelper";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook"; import { messageStore } from "@/stores";
import { resetSortCardModal } from "@/reducers/duel/mod";
import { selectSortCardModal } from "@/reducers/duel/modal/sortCardModalSlice";
import { store } from "@/store";
import { messageStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
const { sortCardModal } = messageStore; const { sortCardModal } = messageStore;
export const SortCardModal = () => { export const SortCardModal = () => {
// const dispatch = store.dispatch;
const snapSortCardModal = useSnapshot(sortCardModal); const snapSortCardModal = useSnapshot(sortCardModal);
// const state = useAppSelector(selectSortCardModal);
// const isOpen = state.isOpen;
// const options = state.options;
const isOpen = snapSortCardModal.isOpen; const isOpen = snapSortCardModal.isOpen;
const options = snapSortCardModal.options; const options = snapSortCardModal.options;
const [items, setItems] = useState(options); const [items, setItems] = useState(options);
...@@ -52,7 +42,6 @@ export const SortCardModal = () => { ...@@ -52,7 +42,6 @@ export const SortCardModal = () => {
const onFinish = () => { const onFinish = () => {
sendSortCardResponse(items.map((item) => item.response)); sendSortCardResponse(items.map((item) => item.response));
// dispatch(resetSortCardModal());
sortCardModal.isOpen = false; sortCardModal.isOpen = false;
sortCardModal.options = []; sortCardModal.options = [];
}; };
......
...@@ -4,12 +4,6 @@ import { Avatar } from "antd"; ...@@ -4,12 +4,6 @@ import { Avatar } from "antd";
import React from "react"; import React from "react";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook";
import {
selectMeInitInfo,
selectOpInitInfo,
} from "@/reducers/duel/initInfoSlice";
import { selectWaiting } from "@/reducers/duel/mod";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
...@@ -18,14 +12,11 @@ const avatarSize = 40; ...@@ -18,14 +12,11 @@ const avatarSize = 40;
const ME_VALUE = "myself"; const ME_VALUE = "myself";
const OP_VALUE = "opponent"; const OP_VALUE = "opponent";
import { matStore } from "@/valtioStores";
import { useSnapshot } from "valtio"; import { useSnapshot } from "valtio";
export const PlayerStatus = () => { import { matStore } from "@/stores";
// const meInfo = useAppSelector(selectMeInitInfo);
// const opInfo = useAppSelector(selectOpInitInfo);
// const waiting = useAppSelector(selectWaiting) || false;
export const PlayerStatus = () => {
const meInfo = useSnapshot(matStore.initInfo.me); const meInfo = useSnapshot(matStore.initInfo.me);
const opInfo = useSnapshot(matStore.initInfo.op); const opInfo = useSnapshot(matStore.initInfo.op);
const waiting = useSnapshot(matStore).waiting; const waiting = useSnapshot(matStore).waiting;
......
import { MessageOutlined } from "@ant-design/icons"; import { MessageOutlined } from "@ant-design/icons";
import { Timeline, TimelineItemProps } from "antd"; import { Timeline, TimelineItemProps } from "antd";
import React, { useContext, useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useSnapshot } from "valtio"; import { useSnapshot } from "valtio";
import { useAppSelector } from "@/hook"; import { chatStore } from "@/stores";
import { selectChat } from "@/reducers/chatSlice";
import { chatStore } from "@/valtioStores";
export const DuelTimeLine = () => { export const DuelTimeLine = () => {
const [items, setItems] = useState<TimelineItemProps[]>([]); const [items, setItems] = useState<TimelineItemProps[]>([]);
// const chat = useAppSelector(selectChat);
const stateChat = chatStore; const stateChat = chatStore;
const snapChat = useSnapshot(stateChat); const snapChat = useSnapshot(stateChat);
......
import { Button } from "antd"; import { Button } from "antd";
import React from "react"; import React from "react";
import { useSnapshot } from "valtio";
import { sendSelectEffectYnResponse } from "@/api/ocgcore/ocgHelper"; import { sendSelectEffectYnResponse } from "@/api";
import { useAppSelector } from "@/hook"; import { matStore, messageStore } from "@/stores";
import { selectHint } from "@/reducers/duel/hintSlice";
import { setYesNoModalIsOpen } from "@/reducers/duel/mod";
import {
selectYesNoModalIsOpen,
selectYesNOModalMsg,
} from "@/reducers/duel/modal/mod";
import { store } from "@/store";
import { DragModal } from "./DragModal"; import { DragModal } from "./DragModal";
import { messageStore, matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const { yesNoModal } = messageStore; const { yesNoModal } = messageStore;
export const YesNoModal = () => { export const YesNoModal = () => {
// const dispatch = store.dispatch;
// const isOpen = useAppSelector(selectYesNoModalIsOpen);
// const msg = useAppSelector(selectYesNOModalMsg);
// const hint = useAppSelector(selectHint);
const snapYesNoModal = useSnapshot(yesNoModal); const snapYesNoModal = useSnapshot(yesNoModal);
const isOpen = snapYesNoModal.isOpen; const isOpen = snapYesNoModal.isOpen;
const msg = snapYesNoModal.msg; const msg = snapYesNoModal.msg;
......
import * as BABYLON from "@babylonjs/core"; import * as BABYLON from "@babylonjs/core";
import { useSnapshot } from "valtio";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook"; import { matStore } from "@/stores";
import {
selectMeBanishedZone,
selectOpBanishedZone,
} from "@/reducers/duel/banishedZoneSlice";
import { cardSlotRotation } from "../utils"; import { cardSlotRotation } from "../utils";
import { Depth, SingleSlot } from "./SingleSlot"; import { Depth, SingleSlot } from "./SingleSlot";
import { matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
export const BanishedZone = () => { export const BanishedZone = () => {
// const meBanishedZone = useAppSelector(selectMeBanishedZone).inner;
// const opBanishedZone = useAppSelector(selectOpBanishedZone).inner;
const meBanishedZone = useSnapshot(matStore.banishedZones.me); const meBanishedZone = useSnapshot(matStore.banishedZones.me);
const opBanishedZone = useSnapshot(matStore.banishedZones.op); const opBanishedZone = useSnapshot(matStore.banishedZones.op);
......
import * as BABYLON from "@babylonjs/core"; import * as BABYLON from "@babylonjs/core";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook";
import { selectMeDeck, selectOpDeck } from "@/reducers/duel/deckSlice";
import { cardSlotRotation } from "../utils"; import { cardSlotRotation } from "../utils";
import { Depth, SingleSlot } from "./SingleSlot"; import { Depth, SingleSlot } from "./SingleSlot";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
import { matStore } from "@/valtioStores";
import { useSnapshot } from "valtio"; import { useSnapshot } from "valtio";
export const CommonDeck = () => { import { matStore } from "@/stores";
// const meDeck = useAppSelector(selectMeDeck).inner;
// const opDeck = useAppSelector(selectOpDeck).inner;
export const CommonDeck = () => {
const meDeck = useSnapshot(matStore.decks.me); const meDeck = useSnapshot(matStore.decks.me);
const opDeck = useSnapshot(matStore.decks.op); const opDeck = useSnapshot(matStore.decks.op);
......
import * as BABYLON from "@babylonjs/core"; import * as BABYLON from "@babylonjs/core";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook";
import {
selectMeExtraDeck,
selectOpExtraDeck,
} from "@/reducers/duel/extraDeckSlice";
import { cardSlotRotation } from "../utils"; import { cardSlotRotation } from "../utils";
import { Depth, SingleSlot } from "./SingleSlot"; import { Depth, SingleSlot } from "./SingleSlot";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
import { matStore } from "@/valtioStores";
import { useSnapshot } from "valtio"; import { useSnapshot } from "valtio";
import { matStore } from "@/stores";
export const ExtraDeck = () => { export const ExtraDeck = () => {
// const meExtraDeck = useAppSelector(selectMeExtraDeck).inner;
// const opExtraDeck = useAppSelector(selectOpExtraDeck).inner;
const meExtraDeck = useSnapshot(matStore.extraDecks.me); const meExtraDeck = useSnapshot(matStore.extraDecks.me);
const opExtraDeck = useSnapshot(matStore.extraDecks.op); const opExtraDeck = useSnapshot(matStore.extraDecks.op);
......
import * as BABYLON from "@babylonjs/core"; import * as BABYLON from "@babylonjs/core";
import { useSnapshot } from "valtio";
import { ygopro } from "@/api";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook"; import { clearAllPlaceInteradtivities, matStore } from "@/stores";
import { selectMeMagics, selectOpMagics } from "@/reducers/duel/magicSlice";
import { clearMagicPlaceInteractivities } from "@/reducers/duel/mod";
import { cardSlotRotation } from "../utils"; import { cardSlotRotation } from "../utils";
import { FixedSlot } from "./FixedSlot"; import { FixedSlot } from "./FixedSlot";
import { Depth } from "./SingleSlot"; import { Depth } from "./SingleSlot";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
import { matStore, clearAllPlaceInteradtivities } from "@/valtioStores";
import { useSnapshot } from "valtio";
export const Field = () => { export const Field = () => {
// const meField = useAppSelector(selectMeMagics).inner.find(
// (_, sequence) => sequence == 5
// );
// const opField = useAppSelector(selectOpMagics).inner.find(
// (_, sequence) => sequence == 5
// );
// 这儿的find可能是出于某种考虑,以后再深思 // 这儿的find可能是出于某种考虑,以后再深思
const meFieldState = matStore.magics.me[5]; const meFieldState = matStore.magics.me[5];
const meField = useSnapshot(meFieldState); const meField = useSnapshot(meFieldState);
...@@ -29,7 +18,8 @@ export const Field = () => { ...@@ -29,7 +18,8 @@ export const Field = () => {
const opField = useSnapshot(opFieldState); const opField = useSnapshot(opFieldState);
const clearPlaceInteractivitiesAction = (controller: number) => const clearPlaceInteractivitiesAction = (controller: number) =>
matStore.magics.of(controller).clearPlaceInteractivity(); clearAllPlaceInteradtivities(controller, ygopro.CardZone.MZONE); // 应该是对的
return ( return (
<> <>
{meField ? ( {meField ? (
...@@ -38,7 +28,6 @@ export const Field = () => { ...@@ -38,7 +28,6 @@ export const Field = () => {
sequence={0} sequence={0}
position={fieldPosition(0)} position={fieldPosition(0)}
rotation={cardSlotRotation(false)} rotation={cardSlotRotation(false)}
// clearPlaceInteractivitiesAction={clearMagicPlaceInteractivities}
clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction} clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction}
/> />
) : ( ) : (
...@@ -50,7 +39,6 @@ export const Field = () => { ...@@ -50,7 +39,6 @@ export const Field = () => {
sequence={0} sequence={0}
position={fieldPosition(1)} position={fieldPosition(1)}
rotation={cardSlotRotation(true)} rotation={cardSlotRotation(true)}
// clearPlaceInteractivitiesAction={clearMagicPlaceInteractivities}
clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction} clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction}
/> />
) : ( ) : (
......
import * as BABYLON from "@babylonjs/core"; import * as BABYLON from "@babylonjs/core";
import { ActionCreatorWithPayload } from "@reduxjs/toolkit";
import { useRef } from "react"; import { useRef } from "react";
import { useSnapshot } from "valtio";
import { ygopro } from "@/api"; import { sendSelectPlaceResponse, ygopro } from "@/api";
import { sendSelectPlaceResponse } from "@/api/ocgcore/ocgHelper";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useClick } from "@/hook"; import { useClick } from "@/hook";
// import { CardState } from "@/reducers/duel/generic";
import { import {
setCardListModalInfo,
setCardListModalIsOpen,
setCardModalCounters,
setCardModalInteractivies,
setCardModalIsOpen,
setCardModalMeta,
} from "@/reducers/duel/mod";
import { store } from "@/store";
import { interactTypeToString } from "../utils";
import { useSnapshot, INTERNAL_Snapshot } from "valtio";
import {
clearAllIdleInteractivities,
type CardState, type CardState,
clearAllPlaceInteradtivities, clearAllPlaceInteradtivities,
messageStore, messageStore,
} from "@/valtioStores"; } from "@/stores";
import { interactTypeToString } from "../utils";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
...@@ -43,13 +29,11 @@ export const FixedSlot = (props: { ...@@ -43,13 +29,11 @@ export const FixedSlot = (props: {
position: BABYLON.Vector3; position: BABYLON.Vector3;
rotation: BABYLON.Vector3; rotation: BABYLON.Vector3;
deffenseRotation?: BABYLON.Vector3; deffenseRotation?: BABYLON.Vector3;
// clearPlaceInteractivitiesAction: ActionCreatorWithPayload<number, string>;
clearPlaceInteractivitiesAction: (controller: number) => void; clearPlaceInteractivitiesAction: (controller: number) => void;
}) => { }) => {
const planeRef = useRef(null); const planeRef = useRef(null);
const snapState = useSnapshot(props.state); const snapState = useSnapshot(props.state);
// const snapState = props.state;
const rotation = const rotation =
snapState.location.position === ygopro.CardPosition.DEFENSE || snapState.location.position === ygopro.CardPosition.DEFENSE ||
snapState.location.position === ygopro.CardPosition.FACEUP_DEFENSE || snapState.location.position === ygopro.CardPosition.FACEUP_DEFENSE ||
...@@ -58,7 +42,6 @@ export const FixedSlot = (props: { ...@@ -58,7 +42,6 @@ export const FixedSlot = (props: {
: props.rotation; : props.rotation;
const edgesWidth = 2.0; const edgesWidth = 2.0;
const edgesColor = BABYLON.Color4.FromColor3(BABYLON.Color3.Yellow()); const edgesColor = BABYLON.Color4.FromColor3(BABYLON.Color3.Yellow());
// const dispatch = store.dispatch;
const faceDown = const faceDown =
snapState.location.position === ygopro.CardPosition.FACEDOWN_DEFENSE || snapState.location.position === ygopro.CardPosition.FACEDOWN_DEFENSE ||
...@@ -69,8 +52,6 @@ export const FixedSlot = (props: { ...@@ -69,8 +52,6 @@ export const FixedSlot = (props: {
(_event) => { (_event) => {
if (snapState.placeInteractivity) { if (snapState.placeInteractivity) {
sendSelectPlaceResponse(snapState.placeInteractivity.response); sendSelectPlaceResponse(snapState.placeInteractivity.response);
// dispatch(props.clearPlaceInteractivitiesAction(0));
// dispatch(props.clearPlaceInteractivitiesAction(1));
// 其实不应该从外面传进来的... // 其实不应该从外面传进来的...
// props.clearPlaceInteractivitiesAction(0); // props.clearPlaceInteractivitiesAction(0);
// props.clearPlaceInteractivitiesAction(1); // props.clearPlaceInteractivitiesAction(1);
...@@ -78,26 +59,13 @@ export const FixedSlot = (props: { ...@@ -78,26 +59,13 @@ export const FixedSlot = (props: {
clearAllPlaceInteradtivities(1); clearAllPlaceInteradtivities(1);
} else if (snapState.occupant) { } else if (snapState.occupant) {
// 中央弹窗展示选中卡牌信息 // 中央弹窗展示选中卡牌信息
// dispatch(setCardModalMeta(snapState.occupant));
messageStore.cardModal.meta = snapState.occupant; messageStore.cardModal.meta = snapState.occupant;
// dispatch(
// setCardModalInteractivies(
// snapState.idleInteractivities.map((interactivity) => {
// return {
// desc: interactTypeToString(interactivity.interactType),
// response: interactivity.response,
// };
// })
// )
// );
messageStore.cardModal.interactivies = messageStore.cardModal.interactivies =
snapState.idleInteractivities.map((interactivity) => ({ snapState.idleInteractivities.map((interactivity) => ({
desc: interactTypeToString(interactivity.interactType), desc: interactTypeToString(interactivity.interactType),
response: interactivity.response, response: interactivity.response,
})); }));
// dispatch(setCardModalCounters(snapState.counters));
messageStore.cardModal.counters = snapState.counters; messageStore.cardModal.counters = snapState.counters;
// dispatch(setCardModalIsOpen(true));
messageStore.cardModal.isOpen = true; messageStore.cardModal.isOpen = true;
// 侧边栏展示超量素材信息 // 侧边栏展示超量素材信息
...@@ -105,22 +73,11 @@ export const FixedSlot = (props: { ...@@ -105,22 +73,11 @@ export const FixedSlot = (props: {
snapState.overlay_materials && snapState.overlay_materials &&
snapState.overlay_materials.length > 0 snapState.overlay_materials.length > 0
) { ) {
// dispatch(
// setCardListModalInfo(
// snapState.overlay_materials?.map((overlay) => {
// return {
// meta: overlay,
// interactivies: [],
// };
// }) || []
// )
// );
messageStore.cardListModal.list = messageStore.cardListModal.list =
snapState.overlay_materials?.map((overlay) => ({ snapState.overlay_materials?.map((overlay) => ({
meta: overlay, meta: overlay,
interactivies: [], interactivies: [],
})) || []; })) || [];
// dispatch(setCardListModalIsOpen(true));
messageStore.cardListModal.isOpen = true; messageStore.cardListModal.isOpen = true;
} }
} }
......
import * as BABYLON from "@babylonjs/core"; import * as BABYLON from "@babylonjs/core";
import { useSnapshot } from "valtio";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook"; import { matStore } from "@/stores";
import {
selectMeGraveyard,
selectOpGraveyard,
} from "@/reducers/duel/graveyardSlice";
import { cardSlotRotation } from "../utils"; import { cardSlotRotation } from "../utils";
import { Depth, SingleSlot } from "./SingleSlot"; import { Depth, SingleSlot } from "./SingleSlot";
import { matStore } from "@/valtioStores";
import { useSnapshot } from "valtio";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
export const Graveyard = () => { export const Graveyard = () => {
// const meGraveyard = useAppSelector(selectMeGraveyard).inner;
// const opGraveyard = useAppSelector(selectOpGraveyard).inner;
const meGraveyard = useSnapshot(matStore.graveyards.me); const meGraveyard = useSnapshot(matStore.graveyards.me);
const opGraveyard = useSnapshot(matStore.graveyards.op); const opGraveyard = useSnapshot(matStore.graveyards.op);
......
import * as BABYLON from "@babylonjs/core"; import * as BABYLON from "@babylonjs/core";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { useHover } from "react-babylonjs"; import { useHover } from "react-babylonjs";
import { INTERNAL_Snapshot, useSnapshot } from "valtio";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector, useClick } from "@/hook"; import { useClick } from "@/hook";
// import { CardState } from "@/reducers/duel/generic"; import { type CardState, matStore, messageStore } from "@/stores";
import { selectMeHands, selectOpHands } from "@/reducers/duel/handsSlice";
import {
setCardModalInteractivies,
setCardModalIsOpen,
setCardModalMeta,
} from "@/reducers/duel/mod";
import { store } from "@/store";
import { matStore, type CardState, messageStore } from "@/valtioStores";
import { useSnapshot, INTERNAL_Snapshot } from "valtio";
import { animated, useSpring } from "../spring"; import { animated, useSpring } from "../spring";
import { interactTypeToString, zip } from "../utils"; import { interactTypeToString, zip } from "../utils";
...@@ -32,12 +24,8 @@ export const Hands = () => { ...@@ -32,12 +24,8 @@ export const Hands = () => {
const opHandsState = matStore.hands.op; const opHandsState = matStore.hands.op;
const meHandsSnap = useSnapshot(meHandsState); const meHandsSnap = useSnapshot(meHandsState);
const opHandsSnap = useSnapshot(opHandsState); const opHandsSnap = useSnapshot(opHandsState);
// const meHands = useAppSelector(selectMeHands).inner;
// const opHands = useAppSelector(selectOpHands).inner;
const meHandPositions = handPositons(0, meHandsSnap); const meHandPositions = handPositons(0, meHandsSnap);
const opHandPositions = handPositons(1, opHandsSnap); const opHandPositions = handPositons(1, opHandsSnap);
// const meHandPositions = handPositons(0, meHandsState);
// const opHandPositions = handPositons(1, opHandsState);
return ( return (
<> <>
...@@ -49,7 +37,6 @@ export const Hands = () => { ...@@ -49,7 +37,6 @@ export const Hands = () => {
sequence={idx} sequence={idx}
position={position} position={position}
rotation={handRotation} rotation={handRotation}
// cover={(id) => `${NeosConfig.cardImgUrl}/${id}.jpg`}
/> />
); );
})} })}
...@@ -61,7 +48,6 @@ export const Hands = () => { ...@@ -61,7 +48,6 @@ export const Hands = () => {
sequence={idx} sequence={idx}
position={position} position={position}
rotation={handRotation} rotation={handRotation}
// cover={(_) => `${NeosConfig.assetsPath}/card_back.jpg`}
back={true} back={true}
/> />
); );
...@@ -89,7 +75,6 @@ const CHand = (props: { ...@@ -89,7 +75,6 @@ const CHand = (props: {
const state = props.state; const state = props.state;
const [hovered, setHovered] = useState(false); const [hovered, setHovered] = useState(false);
const position = props.position; const position = props.position;
// const dispatch = store.dispatch;
const [spring, api] = useSpring( const [spring, api] = useSpring(
() => ({ () => ({
...@@ -124,26 +109,14 @@ const CHand = (props: { ...@@ -124,26 +109,14 @@ const CHand = (props: {
useClick( useClick(
() => { () => {
if (state.occupant) { if (state.occupant) {
// dispatch(setCardModalMeta(state.occupant));
messageStore.cardModal.meta = state.occupant; messageStore.cardModal.meta = state.occupant;
} }
// dispatch(
// setCardModalInteractivies(
// state.idleInteractivities.map((interactive) => {
// return {
// desc: interactTypeToString(interactive.interactType),
// response: interactive.response,
// };
// })
// )
// );
messageStore.cardModal.interactivies = state.idleInteractivities.map( messageStore.cardModal.interactivies = state.idleInteractivities.map(
(interactive) => ({ (interactive) => ({
desc: interactTypeToString(interactive.interactType), desc: interactTypeToString(interactive.interactType),
response: interactive.response, response: interactive.response,
}) })
); );
// dispatch(setCardModalIsOpen(true));
messageStore.cardModal.isOpen = true; messageStore.cardModal.isOpen = true;
}, },
planeRef, planeRef,
...@@ -162,7 +135,6 @@ const CHand = (props: { ...@@ -162,7 +135,6 @@ const CHand = (props: {
rotation={props.rotation} rotation={props.rotation}
enableEdgesRendering enableEdgesRendering
edgesWidth={ edgesWidth={
// state.idleInteractivities.length > 0 || state.placeInteractivities
state.idleInteractivities.length > 0 || state.placeInteractivity state.idleInteractivities.length > 0 || state.placeInteractivity
? edgesWidth ? edgesWidth
: 0 : 0
...@@ -172,7 +144,6 @@ const CHand = (props: { ...@@ -172,7 +144,6 @@ const CHand = (props: {
<animated.standardMaterial <animated.standardMaterial
name={`hand-mat-${props.sequence}`} name={`hand-mat-${props.sequence}`}
diffuseTexture={ diffuseTexture={
// new BABYLON.Texture(props.cover(state.occupant?.id || 0))
new BABYLON.Texture( new BABYLON.Texture(
props.back props.back
? `${NeosConfig.assetsPath}/card_back.jpg` ? `${NeosConfig.assetsPath}/card_back.jpg`
......
import * as BABYLON from "@babylonjs/core"; import * as BABYLON from "@babylonjs/core";
import { type INTERNAL_Snapshot, useSnapshot } from "valtio";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook"; import { type CardState, matStore } from "@/stores";
// import { CardState } from "@/reducers/duel/generic";
import { selectMeMagics, selectOpMagics } from "@/reducers/duel/magicSlice";
import { clearMagicPlaceInteractivities } from "@/reducers/duel/mod";
import { cardSlotRotation, zip } from "../utils"; import { cardSlotRotation, zip } from "../utils";
import { FixedSlot } from "./FixedSlot"; import { FixedSlot } from "./FixedSlot";
import { matStore, type CardState } from "@/valtioStores";
import { useSnapshot, type INTERNAL_Snapshot } from "valtio";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
// TODO: use config // TODO: use config
const left = -2.15; const left = -2.15;
...@@ -19,9 +14,6 @@ const gap = 1.05; ...@@ -19,9 +14,6 @@ const gap = 1.05;
const transform = NeosConfig.ui.card.transform; const transform = NeosConfig.ui.card.transform;
export const Magics = () => { export const Magics = () => {
// const meMagics = useAppSelector(selectMeMagics).inner;
// const opMagics = useAppSelector(selectOpMagics).inner;
const meMagicState = matStore.magics.me; const meMagicState = matStore.magics.me;
const opMagicState = matStore.magics.op; const opMagicState = matStore.magics.op;
const meMagicsSnap = useSnapshot(meMagicState); const meMagicsSnap = useSnapshot(meMagicState);
...@@ -46,7 +38,6 @@ export const Magics = () => { ...@@ -46,7 +38,6 @@ export const Magics = () => {
sequence={sequence} sequence={sequence}
position={position} position={position}
rotation={cardSlotRotation(false)} rotation={cardSlotRotation(false)}
// clearPlaceInteractivitiesAction={clearMagicPlaceInteractivities}
clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction} clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction}
/> />
); );
...@@ -61,7 +52,6 @@ export const Magics = () => { ...@@ -61,7 +52,6 @@ export const Magics = () => {
sequence={sequence} sequence={sequence}
position={position} position={position}
rotation={cardSlotRotation(true)} rotation={cardSlotRotation(true)}
// clearPlaceInteractivitiesAction={clearMagicPlaceInteractivities}
clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction} clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction}
/> />
); );
......
import "react-babylonjs"; import "react-babylonjs";
import * as BABYLON from "@babylonjs/core"; import * as BABYLON from "@babylonjs/core";
import { type INTERNAL_Snapshot, useSnapshot } from "valtio";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook"; import { type CardState, matStore } from "@/stores";
// import { CardState } from "@/reducers/duel/generic";
import { clearMonsterPlaceInteractivities } from "@/reducers/duel/mod";
import {
selectMeMonsters,
selectOpMonsters,
} from "@/reducers/duel/monstersSlice";
import { cardSlotDefenceRotation, cardSlotRotation, zip } from "../utils"; import { cardSlotDefenceRotation, cardSlotRotation, zip } from "../utils";
import { FixedSlot } from "./FixedSlot"; import { FixedSlot } from "./FixedSlot";
import { matStore, type CardState, messageStore } from "@/valtioStores";
import { useSnapshot, type INTERNAL_Snapshot } from "valtio";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
const transform = NeosConfig.ui.card.transform; const transform = NeosConfig.ui.card.transform;
const floating = NeosConfig.ui.card.floating; const floating = NeosConfig.ui.card.floating;
...@@ -29,9 +21,6 @@ const clearPlaceInteractivitiesAction = (controller: number) => { ...@@ -29,9 +21,6 @@ const clearPlaceInteractivitiesAction = (controller: number) => {
}; };
export const Monsters = () => { export const Monsters = () => {
// const meMonsters = useAppSelector(selectMeMonsters).inner;
// const opMonsters = useAppSelector(selectOpMonsters).inner;
const meMonstersStore = matStore.monsters.me; const meMonstersStore = matStore.monsters.me;
const opMonstersStore = matStore.monsters.op; const opMonstersStore = matStore.monsters.op;
const meMonstersSnap = useSnapshot(meMonstersStore); const meMonstersSnap = useSnapshot(meMonstersStore);
...@@ -51,7 +40,6 @@ export const Monsters = () => { ...@@ -51,7 +40,6 @@ export const Monsters = () => {
position={position} position={position}
rotation={cardSlotRotation(false)} rotation={cardSlotRotation(false)}
deffenseRotation={cardSlotDefenceRotation()} deffenseRotation={cardSlotDefenceRotation()}
// clearPlaceInteractivitiesAction={clearMonsterPlaceInteractivities}
clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction} clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction}
/> />
))} ))}
...@@ -65,7 +53,6 @@ export const Monsters = () => { ...@@ -65,7 +53,6 @@ export const Monsters = () => {
position={position} position={position}
rotation={cardSlotRotation(true)} rotation={cardSlotRotation(true)}
deffenseRotation={cardSlotDefenceRotation()} deffenseRotation={cardSlotDefenceRotation()}
// clearPlaceInteractivitiesAction={clearMonsterPlaceInteractivities}
clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction} clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction}
/> />
))} ))}
...@@ -101,7 +88,6 @@ const ExtraMonsters = (props: { ...@@ -101,7 +88,6 @@ const ExtraMonsters = (props: {
position={leftPosition} position={leftPosition}
rotation={meRotation} rotation={meRotation}
deffenseRotation={cardSlotDefenceRotation()} deffenseRotation={cardSlotDefenceRotation()}
// clearPlaceInteractivitiesAction={clearMonsterPlaceInteractivities}
clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction} clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction}
/> />
<FixedSlot <FixedSlot
...@@ -110,7 +96,6 @@ const ExtraMonsters = (props: { ...@@ -110,7 +96,6 @@ const ExtraMonsters = (props: {
position={rightPosition} position={rightPosition}
rotation={meRotation} rotation={meRotation}
deffenseRotation={cardSlotDefenceRotation()} deffenseRotation={cardSlotDefenceRotation()}
// clearPlaceInteractivitiesAction={clearMonsterPlaceInteractivities}
clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction} clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction}
/> />
<FixedSlot <FixedSlot
...@@ -119,7 +104,7 @@ const ExtraMonsters = (props: { ...@@ -119,7 +104,7 @@ const ExtraMonsters = (props: {
position={rightPosition} position={rightPosition}
rotation={opRotation} rotation={opRotation}
deffenseRotation={cardSlotDefenceRotation()} deffenseRotation={cardSlotDefenceRotation()}
clearPlaceInteractivitiesAction={clearMonsterPlaceInteractivities} clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction}
/> />
<FixedSlot <FixedSlot
state={opRight} state={opRight}
...@@ -127,7 +112,7 @@ const ExtraMonsters = (props: { ...@@ -127,7 +112,7 @@ const ExtraMonsters = (props: {
position={leftPosition} position={leftPosition}
rotation={opRotation} rotation={opRotation}
deffenseRotation={cardSlotDefenceRotation()} deffenseRotation={cardSlotDefenceRotation()}
clearPlaceInteractivitiesAction={clearMonsterPlaceInteractivities} clearPlaceInteractivitiesAction={clearPlaceInteractivitiesAction}
/> />
</> </>
); );
......
import * as BABYLON from "@babylonjs/core"; import * as BABYLON from "@babylonjs/core";
import { useRef } from "react"; import { useRef } from "react";
import { useSnapshot } from "valtio";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useClick } from "@/hook"; import { useClick } from "@/hook";
import { CardState } from "@/reducers/duel/generic"; import { type CardState, messageStore } from "@/stores";
import {
setCardListModalInfo,
setCardListModalIsOpen,
} from "@/reducers/duel/mod";
import { store } from "@/store";
import { interactTypeToString } from "../utils"; import { interactTypeToString } from "../utils";
import { useSnapshot } from "valtio";
import { messageStore } from "@/valtioStores";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
const transform = NeosConfig.ui.card.transform; const transform = NeosConfig.ui.card.transform;
...@@ -26,7 +19,6 @@ export const SingleSlot = (props: { ...@@ -26,7 +19,6 @@ export const SingleSlot = (props: {
}) => { }) => {
const snapState = useSnapshot(props.state); const snapState = useSnapshot(props.state);
const boxRef = useRef(null); const boxRef = useRef(null);
// const dispatch = store.dispatch;
const edgeRender = const edgeRender =
snapState.find((item) => snapState.find((item) =>
item === undefined ? false : item.idleInteractivities.length > 0 item === undefined ? false : item.idleInteractivities.length > 0
...@@ -37,25 +29,6 @@ export const SingleSlot = (props: { ...@@ -37,25 +29,6 @@ export const SingleSlot = (props: {
useClick( useClick(
(_event) => { (_event) => {
if (snapState.length != 0) { if (snapState.length != 0) {
// dispatch(
// setCardListModalInfo(
// snapState
// .filter(
// (item) => item.occupant !== undefined && item.occupant.id !== 0
// )
// .map((item) => {
// return {
// meta: item.occupant,
// interactivies: item.idleInteractivities.map((interactivy) => {
// return {
// desc: interactTypeToString(interactivy.interactType),
// response: interactivy.response,
// };
// }),
// };
// })
// )
// );
messageStore.cardListModal.list = snapState messageStore.cardListModal.list = snapState
.filter( .filter(
(item) => item.occupant !== undefined && item.occupant.id !== 0 (item) => item.occupant !== undefined && item.occupant.id !== 0
......
import { InteractType } from "@/reducers/duel/generic"; import { InteractType } from "@/stores";
export function interactTypeToString(t: InteractType): string { export function interactTypeToString(t: InteractType): string {
switch (t) { switch (t) {
......
...@@ -4,22 +4,13 @@ import { ...@@ -4,22 +4,13 @@ import {
TableOutlined, TableOutlined,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { Button, Modal } from "antd"; import { Button, Modal } from "antd";
import React, { useContext, useEffect } from "react"; import React, { useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { useSnapshot } from "valtio"; import { useSnapshot } from "valtio";
import { sendHandResult, sendTpResult } from "@/api/ocgcore/ocgHelper"; import { sendHandResult, sendTpResult } from "@/api";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook"; import { matStore, moraStore } from "@/stores";
import { selectDuelHsStart } from "@/reducers/duel/mod";
import {
selectHandSelectAble,
selectTpSelectAble,
unSelectHandAble,
unSelectTpAble,
} from "@/reducers/moraSlice";
import { store } from "@/store";
import { moraStore, matStore } from "@/valtioStores";
const { const {
automation: { isAiMode, isAiFirst }, automation: { isAiMode, isAiFirst },
...@@ -30,14 +21,8 @@ const Mora = () => { ...@@ -30,14 +21,8 @@ const Mora = () => {
const snapMora = useSnapshot(moraStore); const snapMora = useSnapshot(moraStore);
const snapMatInitInfo = useSnapshot(matStore.initInfo); const snapMatInitInfo = useSnapshot(matStore.initInfo);
// const dispatch = store.dispatch;
// const selectHandAble = useAppSelector(selectHandSelectAble);
// const selectTpAble = useAppSelector(selectTpSelectAble);
// const duelHsStart = useAppSelector(selectDuelHsStart);
const selectHandAble = snapMora.selectHandAble; const selectHandAble = snapMora.selectHandAble;
const selectTpAble = snapMora.selectTpAble; const selectTpAble = snapMora.selectTpAble;
// const duelHsStart = snapMora.duelStart;
const navigate = useNavigate(); const navigate = useNavigate();
const { player, passWd, ip } = useParams<{ const { player, passWd, ip } = useParams<{
...@@ -48,12 +33,10 @@ const Mora = () => { ...@@ -48,12 +33,10 @@ const Mora = () => {
const handleSelectMora = (selected: string) => { const handleSelectMora = (selected: string) => {
sendHandResult(selected); sendHandResult(selected);
// dispatch(unSelectHandAble());
moraStore.selectHandAble = false; moraStore.selectHandAble = false;
}; };
const handleSelectTp = (isFirst: boolean) => { const handleSelectTp = (isFirst: boolean) => {
sendTpResult(isFirst); sendTpResult(isFirst);
// dispatch(unSelectTpAble());
moraStore.selectTpAble = false; moraStore.selectTpAble = false;
}; };
......
...@@ -19,34 +19,18 @@ import { ...@@ -19,34 +19,18 @@ import {
Space, Space,
Upload, Upload,
} from "antd"; } from "antd";
import React, { useContext, useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import rustInit from "rust-src"; import rustInit from "rust-src";
import { useSnapshot } from "valtio"; import { useSnapshot } from "valtio";
import YGOProDeck from "ygopro-deck-encode"; import YGOProDeck from "ygopro-deck-encode";
import { initStrings, sendHsReady, sendHsStart, sendUpdateDeck } from "@/api";
import { DeckManager, fetchDeck, type IDeck } from "@/api/deck"; import { DeckManager, fetchDeck, type IDeck } from "@/api/deck";
import {
sendHsReady,
sendHsStart,
sendUpdateDeck,
} from "@/api/ocgcore/ocgHelper";
import { initStrings } from "@/api/strings";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { useAppSelector } from "@/hook";
import socketMiddleWare, { socketCmd } from "@/middleware/socket"; import socketMiddleWare, { socketCmd } from "@/middleware/socket";
import sqliteMiddleWare, { sqliteCmd } from "@/middleware/sqlite"; import sqliteMiddleWare, { sqliteCmd } from "@/middleware/sqlite";
import { selectChat } from "@/reducers/chatSlice"; import { store } from "@/stores";
import { initMeExtraDeckMeta } from "@/reducers/duel/extraDeckSlice";
import { selectJoined } from "@/reducers/joinSlice";
import { selectDuelStart } from "@/reducers/moraSlice";
import {
selectIsHost,
selectPlayer0,
selectPlayer1,
} from "@/reducers/playerSlice";
import { store } from "@/store";
import { valtioStore } from "@/valtioStores";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
...@@ -58,7 +42,7 @@ const { ...@@ -58,7 +42,7 @@ const {
} = useConfig(); } = useConfig();
const WaitRoom = () => { const WaitRoom = () => {
const state = valtioStore; const state = store;
const snap = useSnapshot(state); const snap = useSnapshot(state);
const params = useParams<{ const params = useParams<{
player?: string; player?: string;
...@@ -103,13 +87,6 @@ const WaitRoom = () => { ...@@ -103,13 +87,6 @@ const WaitRoom = () => {
} }
}, []); }, []);
const dispatch = store.dispatch;
// const joined = useAppSelector(selectJoined);
// const chat = useAppSelector(selectChat);
// const isHost = useAppSelector(selectIsHost);
// const player0 = useAppSelector(selectPlayer0);
// const player1 = useAppSelector(selectPlayer1);
// const duelStart = useAppSelector(selectDuelStart);
const [api, contextHolder] = notification.useNotification(); const [api, contextHolder] = notification.useNotification();
const joined = snap.joinStore.value; const joined = snap.joinStore.value;
...@@ -160,11 +137,7 @@ const WaitRoom = () => { ...@@ -160,11 +137,7 @@ const WaitRoom = () => {
const onDeckReady = async (deck: IDeck) => { const onDeckReady = async (deck: IDeck) => {
sendUpdateDeck(deck); sendUpdateDeck(deck);
await dispatch( store.matStore.extraDecks.me.add(deck.extra?.reverse() || []);
initMeExtraDeckMeta({ controler: 0, codes: deck.extra?.reverse() || [] })
);
// FIXME 直接写成了me,但不确定是不是对的
valtioStore.matStore.extraDecks.me.add(deck.extra?.reverse() || []);
setChoseDeck(true); setChoseDeck(true);
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment