Conversation
Add AppEventSystem for managing application events, including loading and saving user settings. Introduce GameSettingsManager and UserSettingsManager for handling game and user-specific settings. Refactor LaunchOptions for better command-line argument parsing.
There was a problem hiding this comment.
Pull Request Overview
This PR refactors the settings management system by separating concerns into distinct managers and introducing new data structures. The refactoring improves code organization by splitting monolithic classes into specialized managers for game settings, user settings, and launch options.
Key changes:
- Split
SettingsManagerintoGameSettingsManagerandUserSettingsManagerwith clearly separated responsibilities - Refactored
LaunchOptionsfrom a static utility class into a record-based pattern withLaunchOptionsManager - Introduced new record types (
LaunchOptions,UserSettings) for better data modeling - Added
AppEventSystemto handle application lifecycle events (startup/shutdown) - Updated default window dimensions from properties file (1024x768) vs hardcoded in
UserSettings(1280x960)
Reviewed Changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| settings.properties | Added logic.width and logic.height properties for game window dimensions |
| UserSettings.java | New record class representing user settings with Video and Audio nested classes |
| LaunchOptions.java | New record representing launch options with debug flag |
| AppEventSystem.java | New system for managing application lifecycle events (load/save user settings) |
| UserSettingsManager.java | New manager for loading/saving user settings from TOML files |
| LaunchOptionsManager.java | Refactored from LaunchOptions class to use record-based pattern |
| GameSettingsManager.java | Refactored from SettingsManager to focus on game initialization settings |
| UserSetting.java | Deleted - replaced by UserSettings.java and UserSettingsManager.java |
| SettingsManager.java | Deleted - split into GameSettingsManager and UserSettingsManager |
| Bounceverse.java | Updated to use new manager classes and added onPreInit lifecycle hook |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /** | ||
| * | ||
| * | ||
| * <h1>${@link LaunchOptions}</h1> |
There was a problem hiding this comment.
| } | ||
|
|
||
| /** | ||
| * Lây settings trong game. |
There was a problem hiding this comment.
Corrected spelling of 'Lây' to 'Lấy'.
| * Lây settings trong game. | |
| * Lấy settings trong game. |
| } | ||
|
|
||
| /** Setting về Hình ảnh. */ | ||
| public static final class Video { |
There was a problem hiding this comment.
The default dimensions in UserSettings (1280x960) differ from the logic dimensions in settings.properties (1024x768). This inconsistency could cause confusion. Consider using the same default values or documenting why they differ. The GameSettingsManager uses the properties file values for logical game dimensions, while UserSettings uses these values for the window size, but the relationship between these two sets of dimensions is unclear.
| public static final class Video { | |
| public static final class Video { | |
| /** | |
| * Default window width and height for the game. | |
| * These values (1280x960) represent the initial window size for the user. | |
| * Note: The logical game dimensions (used for internal game logic and rendering) | |
| * are set to 1024x768 in settings.properties. The window size is larger to allow | |
| * for UI scaling, better user experience, or display of additional elements. | |
| * If you change these values, ensure the relationship with logical dimensions is clear. | |
| */ |
| settings.setApplicationMode( | ||
| Boolean.parseBoolean(gameSettings.getProperty("general.devMode")) | ||
| ? ApplicationMode.DEVELOPER | ||
| : (LaunchOptionsManager.getOptions().debug()) |
There was a problem hiding this comment.
Potential NullPointerException if LaunchOptionsManager.getOptions() returns null. This can occur if GameSettingsManager.loadTo() is called before LaunchOptionsManager.load() is invoked. Although the documentation mentions this requirement, consider adding a null check or initializing with a default LaunchOptions value to make the code more robust.
| : (LaunchOptionsManager.getOptions().debug()) | |
| : (LaunchOptionsManager.getOptions() != null && LaunchOptionsManager.getOptions().debug()) |
| * <p><b>Chú ý: Cần loadTo {@link GameSettingsManager#loadTo(GameSettings)} trước khi tải.</b> | ||
| * | ||
| * @param settings Setting muốn loadTo |
There was a problem hiding this comment.
The documentation states 'Cần loadTo {@link GameSettingsManager#loadTo(GameSettings)} trước khi tải' (Need to loadTo GameSettingsManager#loadTo before loading), which appears to be a copy-paste error. The method name 'loadTo' is used as a verb here but should probably just be 'load'. The comment should clarify that GameSettingsManager.loadTo() needs to be called before UserSettingsManager.load() can be used, not that something needs to be 'loadTo'.
| * <p><b>Chú ý: Cần loadTo {@link GameSettingsManager#loadTo(GameSettings)} trước khi tải.</b> | |
| * | |
| * @param settings Setting muốn loadTo | |
| * <p><b>Chú ý: Phải gọi {@link GameSettingsManager#loadTo(GameSettings)} trước khi tải user settings bằng phương thức này.</b> | |
| * | |
| * @param settings Setting người dùng cần tải |
| * | ||
| * <p><b>Chú ý: Cần loadTo {@link GameSettingsManager#loadTo(GameSettings)} trước khi tải.</b> | ||
| * | ||
| * @param settings Setting muốn loadTo |
There was a problem hiding this comment.
Similar to the previous issue, '@param settings Setting muốn loadTo' uses 'loadTo' as a verb. It should be '@param settings Setting muốn load' or '@param settings Setting muốn tải' for consistency with the method's purpose.
| * @param settings Setting muốn loadTo | |
| * @param settings Setting muốn load |
| settings.setWidth(Integer.parseInt(gameSettings.getProperty("logic.width"))); | ||
| settings.setHeight(Integer.parseInt(gameSettings.getProperty("logic.height"))); |
There was a problem hiding this comment.
Potential uncaught 'java.lang.NumberFormatException'.
| settings.setWidth(Integer.parseInt(gameSettings.getProperty("logic.width"))); | |
| settings.setHeight(Integer.parseInt(gameSettings.getProperty("logic.height"))); | |
| try { | |
| settings.setWidth(Integer.parseInt(gameSettings.getProperty("logic.width"))); | |
| } catch (NumberFormatException e) { | |
| System.err.println("Invalid value for logic.width: " + gameSettings.getProperty("logic.width") + ". Using default width 800."); | |
| settings.setWidth(800); | |
| } | |
| try { | |
| settings.setHeight(Integer.parseInt(gameSettings.getProperty("logic.height"))); | |
| } catch (NumberFormatException e) { | |
| System.err.println("Invalid value for logic.height: " + gameSettings.getProperty("logic.height") + ". Using default height 600."); | |
| settings.setHeight(600); | |
| } |
| settings.setWidth(Integer.parseInt(gameSettings.getProperty("logic.width"))); | ||
| settings.setHeight(Integer.parseInt(gameSettings.getProperty("logic.height"))); |
There was a problem hiding this comment.
Potential uncaught 'java.lang.NumberFormatException'.
| settings.setWidth(Integer.parseInt(gameSettings.getProperty("logic.width"))); | |
| settings.setHeight(Integer.parseInt(gameSettings.getProperty("logic.height"))); | |
| try { | |
| settings.setWidth(Integer.parseInt(gameSettings.getProperty("logic.width"))); | |
| } catch (NumberFormatException e) { | |
| System.err.println("Invalid value for logic.width: " + gameSettings.getProperty("logic.width") + ". Using default width 800."); | |
| settings.setWidth(800); | |
| } | |
| try { | |
| settings.setHeight(Integer.parseInt(gameSettings.getProperty("logic.height"))); | |
| } catch (NumberFormatException e) { | |
| System.err.println("Invalid value for logic.height: " + gameSettings.getProperty("logic.height") + ". Using default height 600."); | |
| settings.setHeight(600); | |
| } |
No description provided.