-
Notifications
You must be signed in to change notification settings - Fork 2
feat: scaffold react village generator #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
feat: scaffold react village generator #2
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary of Changes
Hello @Gambitnl, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request introduces a new React application designed to procedurally generate village layouts. It integrates the Wave Function Collapse (WFC) algorithm to create diverse village structures based on user-defined parameters such as village type, size, and specific features. The application provides an intuitive web-based interface for users to interact with the generator and visualize the results, and it's set up for easy deployment.
Highlights
- New React/TypeScript Application: A complete new React and TypeScript application has been scaffolded under the
web/directory, providing the foundation for the village generator. - Village Generation Logic with WFC: Core services (
villageGenerationService.ts) have been implemented to generate village layouts using the Wave Function Collapse (WFC) algorithm, including defining specific WFC tiles and their adjacency rules (village.ts). - Interactive Web UI for Configuration: An interactive web user interface has been developed in
App.tsx, allowing users to select village type (farming, fishing, fortified), size (small, medium), and toggle the inclusion of features like farmland, market, walls, and wells, all controlled by a 'Generate Village' button. - SVG Rendering of Village Layouts: The
VillagePane.tsxcomponent has been created to visually render the generated village layout using SVG elements, effectively displaying roads, various buildings, and walls. - Vercel Deployment Configuration: A
vercel.jsonfile has been added to configure the project for seamless deployment on Vercel, ensuring the compiled web application is correctly served.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments or fill out our survey to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a React-based village generator using Wave Function Collapse. The implementation is a good starting point, but there are several areas for improvement. My review includes feedback on Vercel configuration, dependency management, potential race conditions in React hooks, and code clarity and efficiency in the generation logic. Addressing these points will improve the robustness and maintainability of the new web application.
| "@types/react": "^19.1.9", | ||
| "@types/react-dom": "^19.1.7", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a version mismatch between the React dependencies and their corresponding type definitions. You are using React version 18, but the types are for version 19. This can lead to incorrect type checking, build errors, or unexpected behavior. Please align the versions of the type definitions with the library versions to ensure type safety.
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
| useEffect(() => { | ||
| if (currentWorldBiomeId === 'village') { | ||
| const seed = simpleHash(JSON.stringify(options)); | ||
| generateWfcGrid(seed, options).then((grid) => { | ||
| setVillageLayout(transformGridToLayout(grid, options)); | ||
| }); | ||
| } else { | ||
| setVillageLayout(undefined); | ||
| } | ||
| }, [currentWorldBiomeId, options]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The useEffect hook performs an asynchronous operation but lacks a cleanup function. If the component re-renders with new props (currentWorldBiomeId or options) before the generateWfcGrid promise resolves, you could have a race condition where a stale result incorrectly updates the state. You should add a cleanup function to ignore stale promise resolutions.
Here is an example of how to fix it:
useEffect(() => {
let active = true;
if (currentWorldBiomeId === 'village') {
const seed = simpleHash(JSON.stringify(options));
generateWfcGrid(seed, options).then((grid) => {
if (active) {
setVillageLayout(transformGridToLayout(grid, options));
}
});
} else {
setVillageLayout(undefined);
}
return () => {
active = false;
};
}, [currentWorldBiomeId, options]);| { "src": "web/package.json", "use": "@vercel/static-build", "config": { "distDir": "web" } } | ||
| ], | ||
| "routes": [ | ||
| { "src": "/(.*)", "dest": "/web/$1" } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dest property in this route configuration appears to be incorrect for a Vercel deployment. With @vercel/static-build and distDir: "web", the content of the web directory is served from the project root. This route will rewrite an incoming request like / to /web/, causing Vercel to look for web/index.html inside the output directory, which is not the intended structure. The destination should likely not include the /web prefix to serve files correctly.
{ "src": "/(.*)", "dest": "/$1" }
| "scripts": { | ||
| "start": "npm run build -- --watch", | ||
| "build": "tsc", | ||
| "test": "echo 'No tests specified'" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| const handleSelect = ( | ||
| key: 'type' | 'size' | ||
| ) => (e: React.ChangeEvent<HTMLSelectElement>) => { | ||
| setOptions((prev) => ({ ...prev, [key]: e.target.value as any })); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| <label style={{ marginLeft: '1rem' }}> | ||
| <input | ||
| type="checkbox" | ||
| checked={options.includeFarmland !== false} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The expression checked={options.includeFarmland !== false} can be confusing because it evaluates to true if options.includeFarmland is either true or undefined. A more explicit and common pattern is to use a double negation (!!) to convert the value to a boolean. With !!, undefined correctly becomes false. This makes the intent clearer and the code less prone to bugs. This feedback applies to the other checkboxes in this component as well.
checked={!!options.includeFarmland}| const allowFarmland = options.includeFarmland !== false; | ||
| const allowMarket = options.includeMarket !== false; | ||
| const allowWalls = options.includeWalls !== false; | ||
| const allowWells = options.includeWells !== false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic options.includeFarmland !== false is used to determine if a feature is enabled. This can be ambiguous because it treats undefined as true. A clearer approach is to use the nullish coalescing operator (??) to provide an explicit default value. For example, options.includeFarmland ?? true clearly states that if the option is undefined, it should be treated as true. This improves code readability and maintainability. This applies to allowMarket, allowWalls, and allowWells as well.
| const allowFarmland = options.includeFarmland !== false; | |
| const allowMarket = options.includeMarket !== false; | |
| const allowWalls = options.includeWalls !== false; | |
| const allowWells = options.includeWells !== false; | |
| const allowFarmland = options.includeFarmland ?? true; | |
| const allowMarket = options.includeMarket ?? true; | |
| const allowWalls = options.includeWalls ?? true; | |
| const allowWells = options.includeWells ?? true; |
| if (!allowWalls) layout.walls = []; | ||
| if (!allowFarmland) | ||
| layout.buildings = layout.buildings.filter((b) => b.type !== 'farmland'); | ||
| if (!allowMarket) | ||
| layout.buildings = layout.buildings.filter((b) => b.type !== 'market'); | ||
| if (!allowWells) | ||
| layout.buildings = layout.buildings.filter((b) => b.type !== 'well'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These filtering operations at the end of the function are redundant. The logic inside the forEach loop already checks if a feature (e.g., allowWalls, allowFarmland) is enabled before adding the corresponding elements to the layout. Removing these final filter steps will make the code more efficient and less confusing.
Summary
web/Testing
npm --prefix web testnpm --prefix web run buildhttps://chatgpt.com/codex/tasks/task_e_688e523f6438832fa06a4bdd434be5d7