EFP 3
Relictus Review Report
- Creation Date: 2025-01-30
- Category: Informational
- Status: Final
- Pull Requests: #4
In EFP 2, a plan to review TerraModulus Relictus branch has been made. This EFP describes about the report of the entire review process. In the following, the report will be presented section by section according to the previously made plan.
The source code was originally reviewed with an order but later reorganized by their respective
topics and themes. The review has been conducted as of commit
2ba2b09bf94110efbdc36cd95ce8d74a20835205
. In the following, various content will be
discussed following their headers. Please note that the organization of content in this section has
been aided by Artificial Intelligence (AI).
This section presents commentary on the Minicraft+ codebase, reviewed in preparation for the new TerraModulus project. Observations include evaluations of the existing implementation as well as suggestions aligned with upcoming development directions. Where applicable, proposed changes for TerraModulus are distinguished from recommendations for refining the existing codebase.
The application framework would include a dedicated Main.kt
file,
designed separately for both client and server implementations. This file contains
the entry point main
function, which is responsible for initializing
the application, processing command-line arguments, and launching the primary
handlers essential for execution.
Within the core
package, several critical components define the
foundation of the application's architecture.
The Game
component should be instantiated rather than implemented
solely through static members or as a singleton. Its designated class name
would be TerraModulus
, with the NAME
field defined as
a top-level constant. Meanwhile, the VERSION
field would be managed
through the application profile, ensuring loading during early runtime and later
accessibility via a getter method.
Initializer
class would be incorporated within Main.kt
file, facilitating the initialization of all core threads required for application
functionality, such as rendering and ticking threads.
The io
package would no longer reside within core
,
as its scope is overly generic. At a minimum, several parts would be grouped
into audio
package and the Localization
class would be
separated from it to ensure modular organization. Furthermore, all display elements
would be registered directly to the menu, allowing a simple reload operation to
refresh all elements without reliance on external hooks.
Ticking operations would be centrally managed within the TerraModulus
class. Specifically, menu ticking would be executed there, necessitating that
MenuManager
be placed outside RenderSystem
, although
rendering would still take it as a parameter. World ticking would be handled by
its respective manager, while audio processing would operate in a separate thread
under the control of the audio system.
To enhance clarity, Display
would be renamed to Screen
.
Instead of retaining the original Screen
class, a Canvas
may be introduced to manage display elements more effectively. Screen transitions
would continue to follow a Last-In-First-Out (LIFO) linked list structure;
however, improvements could be made to the handling of screen initialization
and exit procedures. Rather than relying on an initializing function, a
constructor reference could be utilized, particularly since the parent instance
parameter is primarily intended for rendering. Passing a constructor function
and managing parent screens within MenuManager
would offer a more
streamlined approach.
Similarly, the Initializer
class should avoid the use of static
members. Window management would be handled through a dedicated window handler,
which could also oversee error popups when necessary. FPS (Frames Per Second) and
TPS (Ticks Per Second) counters would be regulated within their respective handler
classes, ensuring proper thread management.
Additionally, the application window would be launched at an early stage, following the initialization of essential basic elements. This approach eliminates the necessity of a splash screen without a visible window. The window would always be centered upon launch to ensure a consistent user experience.
Argument parsing would be handled within the Main.kt
file, reinforcing
a structured approach to processing runtime configurations. The run
function would reside within the TerraModulus
class. Moreover, the
getExceptionTrace
function could potentially be repurposed for
detailed error reporting, contributing to improved debugging and system reliability.
The launching arguments would be systematically structured, with all options named using kebab case, each prefixed with double hyphens. Hardware acceleration would be enabled by default; however, a specific launch option to disable it would also be available. The fullscreen parameter would function as a toggle, determining whether the application starts in fullscreen mode. Regardless of the fullscreen setting, the window size configuration would always be applied. If no specific window dimensions were provided, default values would be used to ensure a consistent display.
Certain assets that are not intended for modularization or customization may be designated as internal components. Unless explicitly required, these resources, including logos, would remain at the root level rather than being organized into separate directories.
The ClipboardHandler
would be managed within the broader
InputHandler
, as all input interactions, including keyboard and
mouse operations, would be handled via GLFW (Graphics Library Framework).
Consequently, there would be no necessity to implement separate interfaces for
key input processing. The menu structure would also undergo modifications to
ensure that key inputs are detected only by the relevant menu elements, following
a prioritized approach.
The InputHandler
oversees several functionalities, including input
processing, key mapping, controller states, and key state handling. However,
controller management would be separated into a dedicated
ControllerManager
. The capability of the originally used gamepad library
is relatively limited, necessitating enhancements in controller support. The abstract
Key
class and its subclasses provide essential functionality, and
repeated key states would no longer be required. Consequently,
PhysicalKey
could be simplified, and ControllerKey
would
be deemed unnecessary. Additionally, logical operations such as "or" and "and" could
be incorporated within the Key
class. String-based expressions would
be deprecated, and the PhysicalKey#stayDown
function would likely be
disregarded. Moreover, if key state processing results in a single Key
state, subclasses such as CompoundedKey
and ORKey
would
no longer be required. Key mapping would employ a distinct class rather than relying
on the Key
class.
To improve organization and efficiency, input handling would be structured into
four distinct classes: KeyInputHandler
, TextInputHandler
,
GamepadInputHandler
, and MouseInputHandler
. Among these,
TextInputHandler
would also manage clipboard operations. Text input
queues would be processed only upon request and reset at the start of each tick
cycle. A regex filter could be implemented for validation, and backspace key
operations would follow the same structured processing method. The
releaseAll
method would be omitted, while key hints or hotkeys, despite
being complex, would likely follow a similar implementation method. Modifier keys
would not be handled separately within the handler class. Controller vibration
feedback would be managed by ControllerManager
or another dedicated
class, but controller detection and management would remain within
ControllerManager
.
Key input events triggered by GLFW would be received and queued within the main
ticking thread. Text inputs would be restricted exclusively to text input fields,
while keyboard inputs would remain universally active. Each keystroke transitions
through three states: "just pressed," "down," and "just released," represented as
boolean values. A press event sets "just pressed" and "down" to true
,
while a release event sets "down" to false and "just released" to true
.
At the start of each input tick, both "just pressed" and "just released" states
would be reset to false
. Subsequently, queued input events would be
processed, updating key states accordingly, followed by window ticking operations
that handle input. The ticking frequency might be set to 1.5 times the maximum FPS.
If necessary, an additional ticking thread operating at a constant frequency could
be introduced.
For events such as controller port interactions, listener callbacks would be
used instead of polling events each tick. These events occur infrequently and would
be best handled asynchronously to prevent unnecessary processing overhead.
Furthermore, GLFW-generated controller events inherently include the target
controller information, eliminating the need for additional search operations.
GamepadInputHandler
would likely be activated only when controllers
are enabled.
Input mapping would be managed separately from the input handler, allowing configurations based on user preferences while keeping certain mappings hardcoded. This includes the F3 debug key and advanced modifier functionalities involving Shift, Ctrl, and Alt modifiers. In-game inputs and controllers would follow similar processing principles and be handled within the same class structure. Mapped hotkeys would remain inactive when input fields are engaged, allowing standard printed key inputs while ensuring hardcoded keys such as escape and enter receive the appropriate handling, especially in one-line field or with an Input Method Editor (IME).
Key mapping would employ predefined sets with the keys of constants rather than arbitrary string-based assignments, ensuring clarity in configuration and eliminating the need for loops. Mapping would strictly serve logical purposes, while a separate display mapping would exist for User Interface (UI) representation. Since the mapping configurations would only be used internally in the program, the necessity to use string representation would be ineffective. The mapping would be hardcoded, so a loop would not be used. The final input states resulting from triggered events would be logically combined using "or" operations to ensure all inputs are properly accounted for. However, no sticky key would be realized for this system.
To optimize keyboard interactions for movement and tile selection, two potential input schemes may be considered. One approach involves using movement keys exclusively, with the selected tile automatically aligning with the tile positioned in front of the player. Alternatively, a dual-set input method could be implemented, where one set of keys (e.g., WASD) controls movement, while another set (e.g., arrow keys) allows independent tile selection by directional input.
Controller management would be enhanced through GLFW, allowing users to select their preferred controller. This configuration option would be adjustable via settings but would not be stored persistently on disk. Additionally, the On-Screen Keyboard (OSK) for controllers would remain available, with notable improvements to its underlying functionality.
The OnScreenKeyboardMenu
would likely retain its existing name but would
include a constructor parameter accepting an input field object. A menu handle for
the screen might also be passed, although the exact implementation remains uncertain.
Alternatively, the OSK could function as an "invisible" menu or component, meaning it
would be excluded from ticking and rendering processes unless actively required.
Given the potential variation in key sizes, keys should be mapped through reference
linking as components rather than predefined layouts. If a key reference is
null
, it would indicate that no accessible keys exist in that direction.
Navigation would still be managed via the D-Pad, ensuring seamless controller-based
interaction. The sticky key's state would be stored within the key object itself,
which would also be linked to its final property. A grid layout may be employed to
organize key positioning efficiently.
All key states including whether a key is pressed or selected, would be maintained within the key object. The OSK would operate independently of traditional keyboard input and would automatically hide itself whenever no controller is detected during a tick cycle. Key event triggers from the OSK would be directed to the associated input field for processing.
To ensure flexibility, an abstract class would be introduced, eliminating the need
for \0
as a placeholder for sticky keys. This structure would also allow
for specialized keys that perform actions beyond text entry, such as the switch key
to the layout of numeric and symbolic keys. Positioning would not rely on x and y
coordinates since they are unnecessary for this implementation. Exception should not
be abused, but managed directly within the input field instance and corresponding
menu components. Visibility checks within the ticking function would be unnecessary,
and rendering could be simplified by incorporating sprites into components.
During key mapping configuration, upon the first key release event, all keys pressed concurrently would be recorded as a key combination. However, specific keys, including escape, menu, and Windows keys, would be restricted from inclusion due to contextual compatibility requirements. The escape key would also function as a cancellation trigger during key detection. Notably, the escape key would remain hardcoded for menu control operations.
Dropping an entire item stack would be executed using the sneaking modifier alongside the drop hotkey. If the configured drop key sequence includes the sneak key, it would be considered a conflict. Each mapping would define a set of permitted keys within a predefined constant.
Permitted key sets:
- Typing Keys: Letters, numbers, and punctuation characters on the main keypad, excluding modifiers
- Control Keys: Ctrl, Alt, Shift, Tab, Enter, Esc, Enter, Backspace, Pause/Break, Insert, Delete
- Function Keys: F1 to F12
- Navigation Keys: Home, End, Page Up, Page Down
- Numpad Keys: All numpad keys except Num Lock
- Forbidden Keys: System-wide reserved keys, including lock keys, Win, Context, Print Screen
Although Tab could be categorized as a navigation key, it has been excluded from that set to avoid redundancy. Unlisted keys may be disregarded. While checking conflicts, hardcoded keys would be taken into account to ensure compatibility.
Debugging functionality would be refined to ensure consistency and ease of access. Hotkeys related to F3, primarily used for toggling the debug screen, would remain hardcoded rather than being configurable. To maintain code consistency, an invisible menu session would be introduced to process both standalone F3 inputs and key combinations involving F3. The session would activate upon pressing F3 and deactivate upon sending a command or releasing the key. It would exclusively handle key inputs, triggering commands when applicable. For most keys, a direct command would be dispatched to a target, such as toggling debugging functions. Otherwise, upon release, the system would verify whether an advanced input session had been engaged. If no such session was detected, the debug screen toggle would be executed.
Additionally, the DebugPanelDisplay
, functioning as a Graphical User
Interface (GUI) for commands may be deprecated if command support is fully integrated.
Maintaining this panel would introduce unnecessary complexity, and using in-game chat
for commands could provide a more efficient approach. Many entries currently depend
on this menu, and transitioning to command-based interactions would simplify the
interface.
Likewise, the ListItemSelectDisplay
could be restructured as a menu
dialog. However, since it is exclusively utilized by the debug panel, its
implementation would be unnecessary. Consequently, associated entries within
screen.entry.commands
would also be removed.
All application events would be logged irrespective of severity levels, eliminating the need for separate logging, debugging, or tracing launch options. Debugging functionality would be universally available, with selective toggling permitted in specific areas. Given the ease of creating user-generated content, debugging would be equally accessible. By structuring each class with a single responsibility, logging targets would be clearly identifiable via fully qualified class names, eliminating the necessity for arbitrary behavior-specific "title names". Log4j 2, SLF4J, and kotlin-logging would serve as the primary logging utilities.
The logging system would transition to a different library for improved idiomatic usage. This change would introduce extensive logging configuration capabilities supported by both the library and its public interface. In adherence to Kotlin’s idiomatic principles, loggers would not be manually instantiated in external classes but would be defined based on descriptive class names. This approach ensures syntactic consistency and eliminates the need for custom target names. Since the console would typically be hidden from users, log output would remain as comprehensive as file-appended logs, without filtering. Additionally, logging configurations would be exclusively managed via programmed code, negating the need for customizable configurations. Notably, the Rust components of the application would not incorporate any logging mechanisms.
The debug locale would no longer be necessary, as untranslated strings would already be logged, ensuring careful programming without requiring translation key displays on-screen. Localization files would be stored within assets, with detailed implementation depending on the new asset system. Instead of a dedicated debug locale, a hotkey-based feature could highlight untranslated UI components dynamically. Since all entries would already be loaded into memory, switching languages would not require additional loading processes.
Language settings would be structured as an inner class within the main settings system, aligning with preferences. With the debug locale removed, sorting would be further simplified. GUI improvements would eliminate the need for entry highlighting; instead, selected options could be bordered, bolded, or tinted in a distinguishable color. Upon exiting the menu, the chosen entry would be applied immediately, negating the need for a "save" button. The translation disclaimer could remain, while an option to force Unicode font would not be needed.
The Settings
system would transition to Preferences
,
ensuring that setting values remain independent of UI components. UI elements
should be designed to reference and link to these settings rather than being
treated as direct entries. World generation configurations would exist solely
within the world generation options rather than being global entries.
Additionally, all settings would be structured as type-specified property entries
The settings screen would be unified as SettingsScreen
rather than
maintaining separate OptionsMainMenuDisplay
and
OptionsWorldDisplay
. There would be no functional distinction
between the settings accessible from the main menu and those available during
gameplay. Each option would store both its original and current values, allowing
for comparison during saving and providing a notification if changes have been
made. Further settings menus would be instantiated only upon access, reducing
unnecessary memory usage. The layout structure would primarily follow two models:
Submenus or Tabs navigation, depending on stylistic choices.
Changes would only be applied upon exiting the settings menu. Additionally,
submenu-related buttons would end with an ellipsis when following a submenu-based
layout.
Applying changes only when menus are closed would be a more effective approach for managing settings. As multiple submenus may exist within the settings interface, UI elements linked to settings values should update exclusively upon menu closure. This approach would prevent frequent and potentially disruptive effects when users modify settings multiple times within a session.
To establish clear distinctions, the following definitions apply:
- Settings: The overarching system within an application that governs configurations and operational adjustments, controlling various features and functionalities
- Options: Specific choices within a context, often presented as a list or menu, allowing users to customize their experience or performing specific actions
- Preferences: User-defined selections that determine application behavior, stored persistently
- Configurations: The structural setup of an application’s parameters and options determining behaviors and structures of application or system, specifying how components interact.
To ensure robust error management, the default uncaught exception handler should be initialized as early as possible. This approach guarantees that any uncaught exceptions are properly handled and users receive relevant notifications. Instead of referencing a separate function, a lambda expression should be used, allowing for greater flexibility in error processing. The error message content should be distinct from other caught exceptions to facilitate clear differentiation.
Errors should trigger informational pop-ups only under specific conditions: if they occur before rendering initialization is complete, or if they fall within or outside the scope of the application. For error catching mechanisms, only documented errors should be considered, unless they are managed within the primary exception handler or a designated error processing block.
The RenderingLimitingModel
is an ineffective implementation,
as scaling the UI and managing menus more efficiently would eliminate the
need for excessive stretching and scrolling of entries. Components such
as ScreenEntry
and EntryRenderingUnit
function
more as workarounds rather than solutions, making them visually and
structurally inadequate. A more refined approach using OpenGL would be
pursued.
The screen
package, excluding its subclasses, originally
contained only Display
, Menu
, Toast
,
TutorialDisplayHandler
, and RelPos
. The term
"display" by definition in dictionary refers to a monitor display, whereas
"screens" typically denote sets of visual components presented on the
window canvas.
The title screen would be enhanced with a background, with selectable
entries featuring highlights rather than arrow-based indicators. It
would include a logo, menu entries, a version string and customizable
title texts via asset packs instead of hardcoded conditions. "Splashes"
may be renamed to "title texts" as they may no longer visually splash.
A help message at the bottom would be unnecessary when mouse support is
enabled by default. The version string would be expanded with additional
details. Converting UI elements into distinct components, similar to Java
Abstract Window Toolkit (AWT) or Swing, would eliminate redundant position
recalculations each frame, improving code quality and scope management.
The init
function in TitleDisplay
should not
handle elements related to screen appearance. The "Play" menu entry would
be replaced with separate "Singleplayer" and "Multiplayer" options, followed
by "Settings". Achievements would not be included at this stage. The compact
"Help" menu, with only four entries, would function as a dialog menu for
simplicity. Any layout that completely replaces or overlays existing canvas
components would be categorized as a screen with content as menus and
components, while entry-based structures would be grouped within a menu.
The title screen entries would include "Help" and "Quit". The
PlayDisplay
has already been deprecated, with its two entries
merged into theTitleDisplay
as aforementioned.
Many screen menus would restrict the Esc key from returning to the previous screen. When screens permit navigation back to prior screens, a dedicated return button would be provided to prevent users from unintentionally losing progress.
Only the top-most screen would be interactive. If an upper screen fully
covers lower screens, those lower screens would not be rendered. The
gameplay canvas would also function as a Screen
to allow
for unified management via ScreenManager
. When the gameplay
screen is instantiated, it would become the base screen, with all other
screens removed. Similarly, initiating a world-loading screen would clear
all other screens.
Display
would be redefined as an abstract class and renamed
Screen
. However, the parent
reference would not
be managed within this class but by the screen manager. Additional
functionality would be introduced to enhance menu-related features.
clearScreen
would be removed, and canExit
could
be replaced by an overridable function or a callable screen handle for the
screen. The class structure would resemble a panel rather than a conventional
Display
. Menu selection
would primarily support
keyboard controls, but tab-based navigation would likely suffice.
Arrow-key-based selection would align with layout structures, such as
AWT-style grid or border layouts, rather than relying on manual position
adjustments. onSelectionChange
may not be necessary, except
in cases where it facilitates access to hidden menus through key selection
or mouse hovering when only selectable components are involved. The rendering
mechanism would be revised, removing dependencies on selection index for
rendering depth.
Each menu would have a distinct content structure. Instead of
ListEntry
, component-based implementations would be adapted,
making removeSelectedEntry
obsolete. The system would adopt
a model similar to AWT or Swing. The stack-handling approach in
InventoryMenu
requires further refinement.
As ItemListMenu
transitions to slot-based design, display length
constraints would no longer be necessary. Likewise, cutting and aligning
entries manually would become obsolete, allowing the removal of the
positioning parameter. The menu construction process would prioritize
flexibility through component-based design, including padding adjustments.
Menu
would evolve into a generalized component container rather
than an entry-based structure. It would not contain entries by default, and
container-like components managing entries (such as ListEntry
)
would be handled separately. A foundational abstract menu would exclude
properties such as size, position, title, spacing, frame, selectability,
rendering, and searching, maintaining minimal structural dependencies. The
menu would encapsulate a container, passed as a protected final parameter
via constructor delegation. Components would be managed independently of menus,
which can exclusively handle components. Screen
would follow a
similar concept but would extend its functionality to directly accommodate both
components and menus. The builder and copy constructor patterns currently in
use are inefficient and would be reconsidered.
The searching functionality would be independent of Menu
,
incorporated only when a container requires it. This mechanism would be
powered by an input field and contextual filtering logic rather than fragile
highlighting and excessive scrolling adjustments. Searching would be performed
only upon Enter activation and would deactivate upon
Escape. Component rendering would be should on relative positioning,
eliminating the need for additional translation functions. Visibility states may
be introduced, and some containers may support listeners. Scrolling animations
introduce unnecessary complexity and would be removed, along with dynamic
entry updates, builders, and MenuListEntry
.
An input masking session would be introduced for each tick to regulate input
state checking in menus. This session would be managed by
MenuManager
, allowing specific menu interactions to suppress or
fully override queued inputs dynamically. Such modifications would occur on
demand without affecting physical key detection outside the menu ticking session.
While its necessity and practicality need further evaluation, this system could
improve interaction consistency across menus and screens.
Components would not reference a menu or screen handle when ticking, while menus should always receive the screen handle upon screen ticking. Handles and functionality would be managed within screens and menus, even for locally defined components. Some menus may require fixed frames, though not all would. Rendering functions should be consistently present across screens, menus, and components.
An abstract InventoryScreen
class would be introduced, serving
as the foundation for all menu screens incorporating player inventory
functionality. This class would encompass player inventory menus, crafting
interfaces, and container menus, but not book-related screens. Every inventory
menu would include an item counter, distinct from the item list menu, which
would remain designated for the creative mode item list. Additionally, the OSK
menu should be controlled by an input field rather than parent menus, enabling
flexible dynamic menu additions with prioritized handling.
For screens such as ContainerDisplay
with dual-sided menus,
directional controls should be used without any cyclic traversal across menus.
Vertical menus, however, may require different handling due to their inherent
connectivity, potentially using Tab for navigation. Notably, slot
selection and stack transfers between menus would be available exclusively when
the mouse is disabled for ketboard controls, preventing conflicts with
mouse-driven interactions, similar to tile selection via keyboard controls.
The getOtherIdx
function lacks relevance under this system, and
determining control behavior based on cursor position introduces unnecessary
complexity. A standardized control mechanism would be implemented, with a
refined naming convention replacing "heaviness". Additionally, color fading
should be implemented via the alpha channel.
The CraftingDisplay
would be integrated into
PlayerInvDisplay
, which would subsequently be renamed
PlayerInventoryScreen
. Depending on the implementation approach,
further specialization may be introduced via subclasses such as
SurvivalPlayerInventoryScreen
and
CreativePlayerInventoryScreen
, ensuring logical consistency with
the overall code style. While the recipe system remains undecided, relevant
crafting menus and recipe unlocking mechanics would be addressed in conjunction
with its development. The achievement acquisition method would be revised, as
the current implementation is excessively hardcoded. Additionally, inventory
change listeners could be introduced if necessary to refine the refresh
functionality.
A new recipe system would be introduced, recipe menus and crafting menus would be greatly changed, since all the crafting mechanisms are too similar. Most critically, crafting menus would integrate player storage visibility to enhance inventory interaction.
The InventoryMenu
would accommodate a holder, though not
necessarily limited to an entity. Inventory contents would be linked to the
holder’s inventory, ensuring bidirectional synchronization of updates. Slot
alignment would not be enforced, allowing menu slots to correspond directly
with inventory slots without rigid structuring. The creative inventory would
not be managed within this system, as previously discussed. Inventory menu slots
would register listeners at either the inventory or menu level, depending on
their nature: temporary slots, such as those in crafting interfaces, would be
handled within the menu, whereas persistent slots (i.e., inventory slots) would
be registered within the inventory. Since inventory modifications can occur
outside direct menu interactions, listener registration at the inventory level,
potentially via the holder, would be necessary.
Item stack operations would be managed by the item list menu, with a
well-defined structure supporting both non-inventory item collections and
inventory-based stacks. A wrapper class may be introduced for streamlined
handling, though further implementation details remain to be determined. The
refresh
function may be unnecessary for menu frame updates, while
the description menu would become a tooltip or a separate menu aside.
Some aspects of PlayerInvDisplay
align with previously discussed
elements. The creative mode item list would be accessible through an
independent menu or a tab. The selected slot would be bordered or highlighted,
with item stacks appearing at the cursor while hovering over inventory menus,
leaving the source slot empty, or remaining in the source slot as a reference
for interaction. No help text should be shown, eliminating the method used to
hide the item list menu.
The RepairBenchDisplay
would retain its inventory menu structure,
though storage slots would be preferable to temporary ones, replacing
RepairBenchCarrier
. While this approach introduces a new paradigm
within the codebase, SlotEntry
would transition from an entry-based
system to a direct slot representation. Menus managing stack transfers currently
follow repetitive processes, which could be simplified through an optimized
transfer model. Each slot component would maintain an association with its
backing inventory slot instance. Disabled buttons and empty slots would remain
selectable but non-interactive. Storage spaces would feature attributes or
properties defining their slot types, such as crafting input slots, product slots,
and other specialized configurations. Fishing rod durability tracking could be
simplified to simplify tool mechanisms. The functionalities of slot entries would
predominantly depend on their associated backing slots. RepairInfo
would be regarded as a context generated by the input items, while the carrier
component primarily delineates operational scope within the display class. The
current method of using leading spaces for positioning within strings is
problematic but common within the codebase; replacing slot labels with intuitive
graphical elements would improve clarity. The onAction
function,
currently used only once within a specific scope, could be refactored into a
lambda. The redundant "checking again" mechanism should be converted into
assertions, as its execution is intentional. Stack movement would primarily
target destination slots, though additional interactions such as mouse scrolling
or L1-R1 slot switching would also be supported, behaving similarly to
addToCarrier
operations. If slots are storage-based, stacks would
persist on exit without being automatically dropped. The code structure of
RepairBench
is actually neat, and there could be slots stored in
the entity.
The inventory system, while well-structured, should be moved to a distinct
package separate from item
. If inventories incorporate slots,
they would use mapped slot structures instead of generic lists, potentially
featuring distinct slot sets per storage unit. To support stacking, item
metadata excluding quantity must remain consistent, ensuring compatibility
with a slot-count-driven inventory model. If slots originate from underlying
storage mechanisms, primary inventory capacities would be derived from these
foundational quantity limits.
Item picking functionalities should be generalized for all mobs using inventory slots.
Item stacks would be managed through an inventory provider responsible for
constructing inventories and item managers. Item configurations would align
with provider specifications, including stacking criteria and limitations.
Consequently, stack size would not be hardcoded within individual items or
stacks. While items themselves would not be cloned, stacks should retain this
capability. Item depletion should be validated upon each interaction, invoking
the inventory manager listener upon stack modifications. Interaction methods
should return true
upon successful interactions, potentially
reflecting state changes accordingly.
The RewardChestInventory
could be generalized to a class next
to the UnlimitedInventory
.
The recipe system should be relocated into a separate package. Recipe instantiation should originally be handled through constructors or factory methods, eliminating the need for string parsing during initialization. Direct instance referencing should be used instead of strings or names, ensuring efficiency and reliability. Recipes must be unlocked prior to usage, maintaining integration with the advancement system.
The main recipe processing method should be replaced with script-based execution. However, due to the inherent complexity of scripts, their implementation must align with standardized execution environments rather than directly mirroring the core code structure. Recipes should be treated as resources rather than being hardcoded within the system.
The InfoDisplay
would be removed, with statistics integrated
into the pause menu. Each player would maintain their own set of statistics,
as a part of the server or world data, but not as a unit of server or world,
although it is still possible to have server or world statistics. World-related
information may not be presented here but could be displayed elsewhere as needed.
The MessageDisplay
class serves only two purposes: displaying link
error messages and resource pack descriptions. The former should be replaced
with standard application notifications, while the latter could be merged into
the main menu layout or incorporated via tooltips. As a result, this class
would become obsolete and should be deprecated.
The TempDisplay
component offers little functionality. When
opening an Internet address in a browser, a confirmation popup should always be
displayed, but there is no need to automatically close the screen indicating the
browser action. Instead, only the confirmation popup should close immediately.
Several functionalities currently handled by PopupDisplay
could
be streamlined through tooltips or full-canvas options menus. Submenus with
limited components may be implemented as simplified panes, akin to anonymous
classes, possibly replacing this class. Popups containing only informational
messages could transition into notifications, while those featuring basic
button options could be refactored into a dedicated class, such as
OptionMenu
. This structure would consist of a display message
alongside defined options with names and fallback settings.
Confirmation popups for quitting may not be necessary. Options dialogs that do not exit or transition screens could be full-canvas, while those requiring menu changes could incorporate a frame. Full-canvas screens would feature a lightly dimmed and blurred background or a dedicated background image, complementing the components. When listening for key sequences in the settings menu, a non-full-canvas banner would display active key inputs, ensuring clarity before any key is released. For instance, the confirmation dialog menu for resetting key bindings would include a frame, with its style determined later.
Buttons should not rely on hotkeys, and this structure should be removed entirely, even for Keyboard-Only controls, with a simplified set of selectable options. Additionally, screen resolution may be leveraged for better horizontal arrangement of options, improving usability. Selection entries or button would provide a more intuitive alternative to direct key-listening mechanisms. The options dialog menu would not support Esc for exiting; users must choose an available option instead. The OSK would not require specific handling within this system.
The player entity is categorized as a living entity, distinct from mobs due to its unique control implementation. The primary distinction lies in the control system, allowing entity behaviors to be generalized without requiring excessive subclassing or repetitive implementations. Since player take action would be governed by specific abilities, such functionality should not be integrated into general entities. A revised classification of entity types will be proposed at a later stage.
Entity interactions follow structured event-based processing:
- Actors initiate actions on targets, which receive those actions as events
- Targets represent entities affected by an actor's interaction
- Controllers regulate entity behavior based on triggered events, with multiple controllers potentially managing a single entity
- Events dictate method execution within the code
- Global states refer to the collective conditions across the entire world
All actions are event-driven, meaning that interactions occur only when events are emitted and processed. This includes regular ticking events and discrete updates. Unlike spontaneous occurrences of attacking or using, entities operate through receiver interfaces responsible for damage and usage handling. When a mob or entity initiates an attack or use event against a target, this event is registered within the main event, forming a hierarchical structure of linked actions. Passive consequences stemming from primary events leverage their provided parameters alongside commonly observed global states.
Attack events initiated by controllers should be structured efficiently. They must focus solely on responding to the primary event with predefined arguments and contextual global states. Attack initialization should remain minimal, calculating only the foundational aspects of an attack, while relevant parameters should be assigned by the controller. The main entity structure should not directly manage event responses. Attack actions may instead be managed through independent controllers, with the corresponding attack response solely processing the event rather than managing indirect state changes by the event. Thus, only the damage reception interface should reside within an entity's main structure.
Similarly, use interactions require clarification. Events related to "use" actions may involve tiles or entities as subjects, while "used on" events primarily concern items as subjects. The subject may shift based on the specific event type, but by default, the target would be the subject. Until a refined solution resolves this ambiguity, usage actions should not be split into separate categories. Using the middle mouse button may provide an alternative interaction mechanism, with further details subject to future discussion.
Movement capabilities, including swimming and traversal across surfaces, would be dictated by AI-driven mov controls, ensuring proper contextual application. Additionally, the "on fire" visual effect would be treated as a transient metadata attribute, with entities retaining the ability to reject such properties upon assignment. Fire and burn damage would be processed through the damage source, acting as an argument within the damage-handling system. For the controls, there might be a method that even mods could add by the interface with the default values; this may require Typed Anchor Dynamic Mapping, which will be proposed later.
Damage evaluation would be managed by controls, eliminating redundant checks such
as isAttackable
. Since entities block interactions regardless of their
nature, preliminary validation steps should be omitted, allowing actions to proceed
without additional verification layers. Similar simplifications also apply to
isInvulnerableTo
and isUsable
, reducing inconsistencies
and streamlining API usage.
Interactive box sizing would be adjusted with greater precision, rather than
relying on approximate sprite dimensions. The current implementation using
tickTime
would be deprecated. Temporary timers for event-driven
effects, such as burning damage, would be pooled within dedicated tick-based
handlers per entity, minimizing unnecessary class-level bloat while retaining
separation of responsibilities. Death detection would reside within health-related
systems, while speed modifications would be managed via move controls,
particularly when factoring in speed-altering effects.
The MobAi
subclass would be dismantled, with individual components
such as despawning mechanisms, intelligent behaviors, automation logic, rendering,
and loot processing transferred to specialized controls and handlers.
For EnemyMob
, behavioral intelligence would be dictated by control
mechanisms. The tracking system requires refinement to enhance targeting efficiency.
The attack range should extend beyond direct physical contact, ensuring broader
interaction capacity. All attack-related methods should be consolidated into a
single function, accepting a damage source parameter for streamlined execution.
Several exposed fields in Player
would be concealed behind dedicated
handlers, including delay counters and GUI-related elements, which would not
reside within a general mob class. Potion effects would be managed via
specialized control structures. Tile condition validation for event handling
should be processed within tile logic rather than mob systems unless explicitly
tied to mob behaviors.
Target selection for interactions should prioritize proximity-based identification. If no valid target is within range, no interaction should be initiated. Cursor-based selection should allow for enhanced precision. If an entity obstructs selection within the active range, the tile beneath should not be selectable, even the entity gives no interaction.
The DamageSource
class should incorporate an argument inferred
from DamageType
. The argument would support multiple data
structures applicable across different scenarios. DamageType
would transition into a standard class rather than an enumerated type to
facilitate extensibility and improve interface accessibility.
Tile interactions, including effects triggered upon stepping or collision,
would be processed through predefined standard methods within tile classes.
If interactions require continuous updates, associated tile entities would
be returned. Factory methods such as onTileSet
should be
contained within relevant initialization scopes where tiles are set and
defined. Additional configurations would be determined by tile properties.
Fluid tiles would be categorized separately, incorporating dedicated fluid mechanisms. Tile connection-based texture rendering should be exclusively handled within texture definitions rather than within tile logic. Tile destruction callbacks, such as those triggered by mining or explosions, would follow a standardized method structure, accepting destruction sources or types as parameters.
Finally, getData
methods in tile implementations would be
eliminated, as relevant data would be processed through chunk or tile managers.
The movement mechanisms for Furniture
would be reconsidered in
light of the decimal coordinate system. Lightweight objects may remain entities,
whereas heavier objects, such as Furnace
and Oven
,
would transition into tile-based structures. Additionally, item sprites should
not be stored within entity instances, ensuring separation of visual assets from
entity logic. The use of reflection for copying remains fragile and should be
avoided.
The inclusion of a die
function within furniture structures is
conceptually awkward and should be restructured.
Furniture item implementation should align with furniture mechanisms. If all furniture can be held, players might be able to pick them up using bare hands or a specialized item. However, selectively allowing only certain furniture items to be held would introduce inconsistencies. If furniture items associate data via properties, a corresponding resource key must be registered explicitly, rather than through dynamic registration. Furthermore, furniture without item representations should remain unregistered for its item form unless explicitly required. As a result, not all furniture may be freely accessible to players.
The PowerGloveItem
currently serves as a placeholder for furniture
pickup. Its removal or revision should be determined based on future inventory
system developments.
The TileItem
class would persist, maintaining its function as the
intermediary for direct tile placement. However, the approach depends on broader
decisions regarding tile mechanics. Tiles could transition into items reserved
for creative mode, facilitating expedited placements. TileModel
would act as a default data structure rather than preserving original tile data,
as stacked tiles do not require retained tile data. If tiles lack item-based
representations, an item type containing a single resource key with metadata
encapsulating tile attributes would be introduced. The primary determinant for
placement eligibility would be the tile type.
If TorchTile
remains an item that can be picked up, classifying it
as furniture may be more appropriate. Furniture is inherently designed for
mobility, allowing players to relocate lightweight objects easily, whereas tiles
are fixed structural components. This misalignment in mechanisms creates
inconsistencies in both logical behavior and expected interactions. Additionally,
small decorative tiles such as wall-mounted torches would be designed explicitly
for placement on wall tiles, reinforcing logical coherence within the system.
The mechanisms governing item drops upon player death remain undecided, with
various implementation approaches offering distinct properties. Ultimately,
the chosen method would align with the game's thematic direction. If the
design philosophy prioritizes realism, the system may resemble Rust, where a
fallen player's body retains inventory items. In such a case, the
DeathChest
concept would become unnecessary.
Inventory randomization should be managed within generation-handling systems
rather than being embedded in Chest
. Container inventories should
remain publicly accessible as standardized public interfaces. Since dungeon
mechanisms are no longer relevant, previous implementations can be disregarded
despite potential improvements.
Tile loot drops may be regulated via tile properties. Damage multipliers could be controlled through game rules, ensuring they affect players in appropriate scenarios. The concept of automatic damage revival lacks logical coherence, particularly for tiles without health attributes, as they are primarily influenced by interactions such as mining.
Resource tiles like OreTile
and other rock formations would
yield loot upon each mining action or complete destruction. Their visual
design would avoid exaggerated spiky appearances, adhering to a more
natural aesthetic.
The World
class should be instantiated independently rather
than residing within core
. Additionally, level management should
be delegated to world instances rather than being handled by unrelated classes.
Several generator configurations, including dimensions, would be defined
within assets rather than hardcoded into the program. World settings such as
the seed and world name would be encapsulated within a dedicated configuration
object.
All world-related randomization processes should be specific to instances
and potentially replaceable by the backend engine as needed. Certain fields,
such as the level change listener, last world entry and exit timestamps, lack
practical utility. Dimension transitions should be governed by actual
implementations rather than relying on an unused listener. Moreover, tracking
entry and exit times through direct comparisons are unnecessary when
initialization and termination can be managed via instance creation and
destruction. The approach of resetting sprite animations within these processes
is flawed; sprite animations should instead be handled separately. Maintaining
instances remains more effective than invoking resetGame
.
Additionally, the logic involving Player#respawn
and
Level#add
within the same block introduces unnecessary complexity;
a more semantic and logically structured code approach should be adopted. While
WorldSettings
aligns conceptually with this logic, the broader
implementation still requires improvement.
Under the new entity system, an entity cannot simply be removed from a dimension;
it must be eliminated entirely. However, entities may transition to a different
dimension by modifying coordinates, ensuring no null entries. The
getClosestPlayer
function should be maintained as a general-purpose
helper method, accessible across various processes including commands. Other
relevant methods may also be retained.
The execution of world events, activities, and commands must be carefully evaluated to avoid bypassing critical processes. Improper handling could lead to unintended execution omissions. This includes aspects such as teleportation across dimensions; all necessary unprocessed events should be considered.
There would be several differences due to the new tile system to be proposed.
FenceTile
serves merely as an overlay for ground tiles, but
the simplified tile system resulted in verbose code that should be optimized.
Since HoleTile
lacks functional significance, it would be removed.
Instead, an "air tile" designation would be introduced, also applicable to
InfiniteFallTile
.
Both DirtTile
and SandTile
would require foundational
support. In the absence of underlying tiles or in cases where only air tiles are
present, these tiles would collapse. Additionally, footsteps on such tiles would
generate extra dust particle effects.
Since the conventional depth-based level system would be retired in
favor of independent dimensions with no direct geographical continuity,
StairsTile
would be deprecated. However, stair-like tiles
could still be incorporated as mobility aids for mobs. These tiles could be
composed of various materials and may exist as fragments or incomplete sections.
The original fixed-size level structure would evolve into an unlimited world consisting of chunk-based dimensions. Given that world generation would be no longer constrained by predefined size limitations, structure generation would operate independently of world size constraints. Each dimension would retain a display name and receive a seed derived from the overarching world seed but would not possess specific size parameters. Even if the generator produces a finite world size, additional chunks should remain accessible, albeit empty.
During dimension construction, essential metadata including mob count limits, would be defined. Entity container management would be confined within dimensions and chunks, overseeing entity counts, additions, removals, and transfers. Server-side entity queues for additions and removals would use linked lists within the entity manager. Chunk-level entity managers may be synchronized with dimension-level managers, ensuring consistency across modifications. Entities might be organized within a quadtree structure to facilitate efficient chunk management.
As part of the proposed world system rework, depth indices for dimensions would be eliminated. The notion of "levels" would be discarded in favor of a pure dimension-based structure. The concept of "level" does not currently exist within the revised framework.
Entities would be stored across two distinct mappings. Each chunk would manage its entities using either a quadtree or k-d tree structure. Dimensions would oversee all loaded chunks, featuring an indexing mechanism for querying entities within chunks. The world would handle all loaded dimensions, implementing an indexing system for querying entities across dimensions while maintaining a global map that associates entity classes with collections of entities.
For nearest-entity searches within a specified range, only selected chunks would be considered. Nearest-neighbor search algorithms would be employed, or entities would be filtered by type using a mapped collection before looping through results. Additionally, when selecting all entities within a given range, including those positioned atop a tile, temporary geometries in the physics engine may be used to identify collided objects rather than exclusively relying on centers of entities.
The in-game ticks per second (TPS) would be adjusted to 20 instead of 60. Additionally, the length of a full-day cycle would be set to 20 minutes rather than 18, ensuring a reasonable duration while maintaining alignment with 60-minute mechanism. To preserve performance consistency, the game speed should remain constant and may not be subject to pausing. Several fields would be introduced for tracking game time values:
-
dayTime
: Represents the total number of ticks (time) elapsed during a single game day -
dayCount
: Tracks the number of days that have passed within the game world -
gameTime
: Records the cumulative ticks (time) elapsed throughout gameplay
Time enums representing different phases of the day may not follow uniform quarter divisions, particularly since "0" would correspond to either midnight or midday. Seasonal cycles and variable day lengths may be introduced in future updates, requiring definitive constants to define distinct time phases. Minecraft's approach could serve as a reference, though its daytime ticking structure does not strictly conform to real-world time conventions for "0". Further implementation details would be discussed and finalized later.
Player entity ticking should be entirely independent of UI ticking, as
entities exist within the world system, whereas UI elements function solely
on the client side. Current implementations may handle menu interactions
within entity ticking functions, which is impractical. Instead, such
operations should be delegated to the MenuManager
or a similar
management class, ensuring proper class isolation and separation of
responsibilities.
With the introduction of the new sleeping mechanisms, tracking sleeping
player counts would no longer be necessary. Additionally, Bed
instances would not store color enums; item, entity, and tile display names
managed via translation keys and registry keys rather than defined within
constructors. Removing the player entity from the level upon sleeping is an
illogical design choice and should be revised accordingly.
Future sleeping mechanisms would be reconsidered to maintain consistent game speed and ensure continuous events are not disrupted by time-skipping or acceleration. However, extended nighttime durations may be problematic under certain circumstances. To mitigate this, an alternate dream world dimension could be introduced during sleep, functioning as a single-player environment. If a player sustains significant damage or dies within this dimension, they would instantly wake up in bed. Correspondingly, a biological health system would be developed to integrate this mechanism.
Players would be able to sleep at any time, provided their character reaches a fatigue threshold. This approach allows gameplay to continue seamlessly while preserving in-game consistency. Detailed implementation specifics would be determined later. Additionally, this method avoids performance inefficiencies that could arise from artificially accelerating game ticks.
The sequence in which tick events are executed within a world is crucial. Since tick events can affect entity positions and even their existence, entity existence-related events should be processed at the end of a ticking cycle. Furthermore, players include both local and remote participants, meaning tick operations must rely on signal transmissions while maintaining synchronized entity management. All entities, including their controls and existence states, should be processed simultaneously to ensure consistency.
Chunk managers would refresh entity positions according to updated coordinates, following structured stages for optimized management. If parallel processing of entities is introduced, tick-dependent events should be segregated and queued instead of being executed immediately, allowing for accurate state synchronization.
Users would be assigned unique client IDs, though detailed implementation specifics are yet to be determined.
The server architecture requires comprehensive planning, encompassing serialization, routing, and network communication. Safeguards must be implemented to mitigate non-synchronization issues and data loss. For consistency and compatibility, there should be no fundamental distinction in implementation between single-player and multiplayer, particularly within the server-client framework. Transmission data may be identified using numeric IDs, though the protocol would not support forward or backward compatibility.
Server-side analytics could track active clients based on Launcher activity and periodic pings, similar to Minicraft+. However, this process should not be classified as general telemetry, which collects device information and usage reports. Data collection must occur only with user consent, and users should retain the ability to enable or disable tracking via preferences after the initial launch (as identified by local save data).
Both data collection methods are entirely optional, with accompanying user agreements and terms. Server-side counting would be managed via database records, whereas pings would remain anonymous. Descriptive telemetry and automatic crash reporting, however, may not be anonymous, as they could include device details or account identifiers. Implementation specifics are yet to be finalized, but they represent an important consideration.
The MultiplayerDisplay
offered little meaningful reference.
However, login authentication should be managed by the Launcher, with
client ID, user ID, authorization token, and session ID transmitted via
launch arguments. Additional data may be retrieved by the application
based on these parameters.
Since skins would be managed by the platform’s account system, they should not be processed within the application. Consequently, there would be no in-game preview or customization screen for skins. Instead, skin data would be transmitted only from the server to the client, where local comparison would occur. The watcher thread for skin tracking would no longer be necessary. The Mob Sprite handling process would differ significantly under this structure.
Client IDs would rely on Universally Unique IDs (UUIDs) with specialized modifications. On the server side, all client IDs would be recorded and associated with account IDs. Account IDs, unique UUIDs maintained by the server database, would serve as server player entity IDs (EIDs). These EIDs would be distinct within the server or world, appended with identifiers differentiating players from other entities.
Client IDs would remain unique, permitting multiple Launcher instances across various client devices. However, two clients cannot connect to the same server using identical client IDs, if attempted, a new client ID would be generated. Additionally, multiple clients cannot access the same server under a single account.
In single-player mode, offline gameplay would be supported via a default hardcoded player EID, mapped to account IDs to facilitate guest modes without requiring an account. Although guest mode simplifies implementation, maintaining a system where account-based player EIDs are universally used ensures that server worlds remain playable offline. These safeguards assumed ideal data integrity, with unauthorized modifications ignored.
While EIDs are not strictly network-related, they were originally
categorized under Network
. Instead, they should be reorganized
into utility functions or a dedicated classification.
Client synchronization decisions would be dictated by the server, meaning any invalid player actions could be ignored or reversed at the server’s discretion.
The pause menu structure would introduce SingleplayerPauseScreen
and MultiplayerPauseScreen
, with respective versions allocated
based on game mode. Single-player sessions and LAN hosts would use the
single-player version, whereas multiplayer participants would engage the
multiplayer variant. The menu title would be "Game Menu", featuring:
- Universal options: "Back to Game", "Settings", "Statistics" and "Advancements"
- Singleplayer exclusive options: "Open to LAN", "World Options" and "Save and Quit"
- Multiplayer exclusive options: "Disconnect", with additional functionalities extendable via plugins or mods
Dedicated servers have predefined server commands, whereas single-player mode lacks such functionality. The scope of in-game commands is subject to future discussion. The most possible implementation method would be within the pause menu, pending further review.
The background of the pause menu would display a dimmed gameplay screen, which would remain interactive in terms of rendering but not input, clicking the dimmed screen would not close the menu.
The PlayerDeathDisplay
would transition into
PlayerDeathScreen
, visually similar to the pause menu but with
the gameplay screen frozen at the last frame before death. The header
"You Died!" would accompany the death message. Upon death, the player
entity ceases to exist in the world, yet the player remains present, albeit
in an unspawned state, preventing any interaction with world events.
At this stage, the player may either respawn or quit, with the world continuing to function normally. If instant respawn is enabled, the death screen would be bypassed, and the player would respawn immediately. The quit button functions identically to its counterpart in the pause menu. No additional menus or information would be accessible during this screen.
A SaveManager
or equivalent class would assume the upper-level
functionalities previously managed by FileHandler
. Basic file
helper functions, such as folder deletion and copying, are already available
in Kotlin through Path.deleteRecursively
and
File.copyRecursively
, eliminating the need for additional
implementations. Future asset management should not rely on filesystem-based
listing, as an advanced asset system would be expected to replace this approach.
World loading would be optimized to provide a structured and visually informative process. For instance, loading sessions should incorporate progress bars for both asset loading and world loading. Since resource loading logic operates outside menus, the interface operations should reside within a dedicated loading menu rather than the actual loading operations being embedded in the interface elements. The loading screen should be instantiated alongside the loading session, dynamically updating and refreshing progress as resources are processed. Additionally, logging world names is redundant when proper class structure organization provides sufficient clarity. Resetting the world before initialization is unnecessary when instances are properly instantiated; once loaded, reset values should be disregarded.
The exceptions encountered during world loading are generally justified, as rare failures require immediate termination or cancellation of the process. While existing code structures may be somewhat disorganized, the fundamental approach remains practical.
The save and load system should operate as independent components rather than
existing as direct Save
and Load
classes. Each aspect,
including timing, system handling, and individual responsibilities, should be
distinctly isolated. Preference management should remain autonomous, with no
direct association with world save data.
If a loader fails to locate the intended object, an explicit error should be
generated, signaling the absence of the requested resource. As a result, unknown
objects should not be loaded. The UnknownItem
class should
be deprecated for consistency. Additionally, strict mode should always
enforce immediate loading termination upon encountering errors.
The LevelTransitionDisplay
should function purely as a UI component,
delegating the actual dimension transition process to a dedicated manager. Since
precise progress tracking may not always be possible, the loading screen should
display a standard background alongside status messages. Moreover, dimensions
might not be preloaded in advance; at a minimum, the target chunk must be fully
generated before transition completion.
The LoadingDisplay
would be renamed asWorldLoadingScreen
,
preventing users from bypassing it via the escape key. Given that world loading
occurs chunk by chunk, progress tracking would be segmented accordingly,
reflecting the individual status of each chunk. Corrupted chunks and regions
should be regenerated, with automatic backups created before deletion from the
loaded pool. Missing spawn-area chunks should be dynamically generated and
monitored by WorldCreatingScreen
, which would also handle new world
creation via WorldCreateScreen
. The existing
LoadingDisplay
implementation was somewhat disorderly. Loading
operations should be managed by a dedicated manager class, ensuring
exception handling is properly delegated to menu-driven dialogs rather than the
loading screen itself.
Automatic data fixing would occur within structured loading schemas, assuming previously reported and resolved issues. Instead of menu-based message popups, application notifications would relay relevant alerts. Progress would be handled specially.
Both LegacyLoad
and HistoricLoad
were introduced
to maintain compatibility with older world save formats. Initially,
LegacyLoad
facilitated handling of old save data, whereas
HistoricLoad
was subsequently introduced to distinguish
between the period when version tracking was not originally considered and the
time when versioning became included among old versions. Significant structural
shifts following the legacy phase warranted this separation.
Additionally, HistoricLoad
introduced a stricter conditional checking
methodology in the codebase, moving away from previous implementations that relied
predominantly on the simple if-else statements and switch-case logics. This change
was driven by the reliance on text-based comma-separated values (CSV) format, which
required extensive string parsing, while the following approach of using JavaScript
Object Notation (JSON) also conforms to this. By using this approach, potential
errors could be minimized while maintaining essential support for older saves.
Future iterations of the save system would adhere to a schema-driven framework, ensuring robust backward compatibility. This approach would enable progressive fixes for outdated saves, applying predefined schemas that gradually improve structural integrity. These data fixers should be static and immutable, implemented as singletons within the codebase. Exception management would incorporate contextual detail, offering different behaviors based on operational mode:
- Compatible mode permits special accommodations for older formats and corrupted data.
- Strict mode enforces immediate failure upon encountering inconsistencies.
Save operations should be independently structured rather than housed within
a unified Save
class. Serialization would be modular,
tailored to different data objects such as entities, ensuring all dynamic tags
are properly processed during save operations. A dedicated WorldSave
class would be introduced to oversee world-specific save data, facilitating
logical and structural serialization processes. Preference settings could
use general serialization, given their inherent key-value structure.
The Rust component would oversee encoding of serialized objects into save files.
It is important to distinguish save versioning from game or public interface versions. Instead of aligning with standard game updates, world saves would be tracked through an independent version number, incremented sequentially for identification.
World names should remain unrestricted, requiring an alternate approach for directory naming. This would involve generating unique identifiers using a randomized alphanumeric character table indexed by an incrementing counter. Both the table and counter would be maintained as internal data within the client application. Under normal operation, world directories should remain unmodified, as an internal lookup table stores directory names for preference-related local user data, such as the last played world. Since unexpected name collisions are possible, warnings would be issued when duplicates arise, prompting the system to skip conflicting identifiers. The identifier format would be base-36 and may be randomized. Server-related data would not be stored on the client side but transmitted on demand, with only primary metadata and configurations retained locally. Given this approach, there would be no need for regular expression-based name validation.
Players should primarily manage worlds through the application rather than a file manager, using advanced editors where applicable. The application should facilitate world import, export, and backup creation, features that might be supported within the launcher itself. Duplicate world names would be permitted, though warnings should inform users when identical names are detected. The application should preserve user-defined names rather than modifying them for uniqueness.
The WorldCreateDisplay
would be renamed and accessed through the
world list screen, which displays all locally stored worlds. This interface
would solely process user inputs and configurations without saving changes
until the world creation process begins. If any fields remain empty or set to
"default", predefined values would be assigned automatically. The seed input
field would accept any characters and hash them through a custom hashing
function, even when numeric values are entered. An option may be provided to
input a true numeric seed separately near the input field. Fields
containing invalid characters or unrecognized values should be
flagged as "unparsable", disabling the completion button. Users would not be
shown the actual directory name assigned to the world.
Settings fields would be initialized within this screen but not retained
post-world creation. They should not persist as global states within places like
the Settings
class. Instead, the WorldSettings
class
should act as a dedicated record class storing all values, isolated from the
screen logic.
Within the world list screen, users would have access to operations such as
importing, exporting, copying, deleting, and creating worlds, with the
middle three restricted to existing worlds. The WorldInfo
class
would resemble a lightweight record class, along with world data size
information. Users would be able to customize world icons, although the
default icon remains uniform across all entries. The displayed world version
would reflect the last accessed game version, rather than the actual data
format version.
Directory names would not be visible but should be accessible via a button on the selected entry, with a folder icon labelled "Open Folder", avoiding disabled button being shown. Users must select a world and click the play button to launch it, though an optional double-click quick access action could be enabled in preferences. Given a more refined and expansive UI, world information would be embedded within each entry, rather than appearing in a separate menu. If stored preferences reference a nonexistent world key, those entries should be designated as unknown.
While the world list screen remains open, a watcher thread would monitor filesystem and operating system (OS) notifications for updates. Any operations performed within the screen menu should transmit selected world data as arguments, avoiding reliance on static fields. Redundant code in the ticking method should be minimized through refactoring and splitting.
World loading procedures would undergo significant restructuring. The existing
methods setWorldName
and hasLoadedWorld
should be removed,
as their implementations are conceptually flawed. getValidWorldName
would no longer be necessary.
Copying a world may function as a straightforward duplication, with "Copy of" prefixed to the original world name. Users would be required to manually edit the name post-duplication or enter a custom name via a dialog, similar to the IntelliJ rename prompt.
The ConnectTile
class should be eliminated. Given the theoretically
infinite world size, visible or discoverable boundaries should not exist under
normal gameplay conditions. Players should be constrained within soft world
boundaries, preventing standard access beyond defined limits.
Certain rock tiles may contain varying concentrations of ores and minerals.
Only the chunk generator within a dimension would use the dimension seed or world seed during initialization. Other randomized events should rely on thread-specific random number generators. Generation processes by covered generators created during dimension initialization should begin only after explicit generation commands, ensuring controlled execution rather than immediate world filling. Arbitrary placement of structures at specific locations should be discouraged unless dictated by a larger generative pattern.
World generation would be governed by a manager, which maintains registries of generation parameters, functions, and configurations. A random number generator with preset seed values would drive the generation process. The generator should remain active throughout world loading for continuous chunk generation. Generation configurations should be modular, stored separately to allow for public customization rather than being hardcoded. The interface should provide customization options for generator configurations, including sampling functions and randomization algorithms.
If the world size is theoretically unlimited, validation mechanisms should be unnecessary, assuming robust generator design. Testing functions may pose challenges due to fragmented content generation, complicating validation methodologies.
If world generation incorporates high variability, conventional techniques such as switch-case structures, loops, and if-else conditions may prove insufficient. Even when fully programmatic approaches are used, constant values should be effectively managed at the field or top level. Additionally, cave structures would not be exclusively planar.
Dungeon generation exemplifies non-standard dimension creation, dictated by large-scale patterns rather than general algorithms. Boss rooms and dungeon gate structures are generated toward the center, requiring specialized logic. To accommodate such designs, scripting may be necessary, instead of conventional data structures like simple lists of attributes and properties formatted in JSON.
Early world generation including terrains would be handled by the Rust part, with chunk data subsequently transmitted to Kotlin for secondary population processes.
- Features are small-scale decorative elements, typically tile placements.
- Structures consist of large-scale templates with complex logic, including preconfigured tile and entity placements.
- Jigsaws serve as presets for templates used in structures.
Map generation testing functions should be excluded from production code,
as they introduce redundancy within released builds and remain inaccessible
without enabling hidden launch parameters. A separate module like
demo
would allow manual parameter input for visual validation
of configurations and algorithms.
When an entity is introduced into the world, a unique identifier would
be assigned through its constructor, ensuring uniqueness and immutability within
the world instance. Entity removal would be governed by the world’s ticking
system per update, eliminating the need for a dedicated boolean field tracking
entity existence. Since an entity’s presence cannot be guaranteed beyond the
current tick, references to target entities may be transient, avoiding persistence
beyond a single tick cycle. If there exists any component storing entity references,
such behavior should be supported by the controls managed by the target entities,
ensuring appropriate destruction; thus, omnidirectional incoming reference may not
be recommended. Entity models should be concealed from direct external
interactions, relying solely on internal state transitions. A potential
EntityPrototype
record class may be introduced to store control
instances before entity construction. Additionally, color field in entity is
redundant and should be excluded.
Despawning would be facilitated by a dedicated control module, ensuring
entities that do not support despawning retain null control references. This
approach extends to both removal and entity death scenarios. Methods "delegated"
to control operations could be structured as inline extension functions,
serving as lightweight utility methods. Since controls can be dynamically
assigned, their scope would remain unrestricted. Similar logic referred from
ItemHolder
, with control classes potentially leveraging extension
functions for master classes like Entity
.
There could be more details in the mechanisms of Composter
, but it
might still depend on the direction of the game. Therefore, it would be more
complex and fancy.
The walkDist
field in Mob
is exclusively tied to sprite
animations and serves no additional purpose. Animation-related data should be
consolidated into an isolated object, ensuring responsibility is managed
independently of the master class. Walking distance tracking for statistics
should shift to move control modules, reinforcing modularity. Another dedicated
object should store all geological data, such as position and
direction, rather than scattering related fields within the mob structure.
Attack cooldown logic should be carefully balanced, ensuring fairness in
both offensive and defensive engagements, rather than a short-period immunity
system that lacks strategic coherence. A Measure
data monitoring
class may be introduced to store both bounds and counter values for
statistical tracking.
Passive mob behaviors, such as grazing, should incorporate realistic action countdowns rather than arbitrary event triggers. Both hostile and neutral mobs should feature enemy-tracking references, allowing intelligent behavior across different models. Current code indicates that the spawners are immune to creepers, though its chaotic implementation should be refined. Many mobs exhibit overly simplistic mechanisms, failing to convey clear behavioral differentiation
Mobs may be primarily generated during world creation, foregoing natural
despawning mechanics for added realism. The noActionTime
field in
Mob
merely functions as a despawning check and lacks broader
significance, and the speed
field similarly lacks meaningful utility.
Explosion damage should be applied directly to affected entities instead of being
processed through an event interface like onExploded
. While the mob
level mechanism remains a potential feature, universal implementation is
unlikely.
Spawning and despawning conditions should be adaptable to gameplay design and thematic direction. Since mobs are expected to spawn only during world generation, natural spawning systems should not be implemented, leaving chunk managers uninvolved in ongoing mob population dynamics. This means that spawner-like devices would not exist, with all standard structures spawned exclusively within desired areas during generation. Village generation, for example, should conform to standardized structure generation rules rather than ad hoc placement. Certain rock tiles may contain varying levels of ore or mineral content, supporting resource diversity within the terrain.
The Spawner
mechanism is overly "reflective", making its
implementation in TerraModulus improbable. If mob-generation devices
are required, a more robust interface design should replace low-level
structural dependencies. Additionally, daylight detection mechanisms for
spawn prevention may require optimization if the lighting system undergoes
revision.
Having both isSolid
and blocks
for collision conditions
is redundant. A more effective approach would be relying solely on
blocks
while dynamically assessing entity data upon collision when
necessary.
Since movement would be primarily governed by the physics engine, explicit
move
method calls for entities are unnecessary. However, velocity and
acceleration control remain crucial, and should be managed through dedicated
move control modules. The previous sub-stepping implementation attempted to divide
movement into discrete units, but this approach becomes impractical within a decimal
coordinate system. Prior to the introduction of the improved algorithm, tunneling
artifacts occurred at higher speeds, which was a known issue that had been
previously reported.
The handling of Arrow
had been previously discussed, and its
integration into the new entity system would significantly improve
collision detection. The logic referencing tile ID 16 (lapis ore) appears
misplaced, with no clear rationale for its inclusion in entity behavior checks.
While ItemEntity
would not feature inherent acceleration, initial
velocity and ground friction would still be considered. The current implementation
misinterprets velocity and acceleration principles, leading to confusion.
Ideally, each ItemEntity
instance should represent a stack of items,
with distinct properties for total elapsed time and remaining time until deletion.
If the remaining time is null, the entity should persist indefinitely. The
two fields currently designated for synchronization serve little practical purpose.
With a 3D world system, vertical motion calculations for animations would
be directly handled via physics, while shadow rendering would be standardized
across all entities. Entity initialization should leverage factory methods,
rather than relying on Level
for instantiation. Additionally,
initial direction and velocity assignments should be handled through
specialized factory methods for, e.g., item and loot dropping.
The Tnt
class would remain classified as Furniture,
but with enhanced visual effects for explosion interactions. Explosion
mechanism for both entities and tiles should conform to generalized explosion
algorithms, considering exposure factors and interaction ranges. Calculation
methods for entities and tiles should remain distinct, though shared
foundational attributes could streamline consistency. Explosion mechanism
may support different explosion types, such as gas-based or
fire-based detonations, although it may just be using different attribute
values.
Character movement should follow gradual velocity increases, simulating realistic acceleration rather than initiating motion instantaneously; friction calculations may be involved. Knockback effects from external forces should be processed as impact events, converting external force into a constant velocity, counteracted by environmental resistance (ground friction or air drag).
The burn command for mobs should be structured as a dynamic property assignment, allowing flexibility rather than implementing it as a static function.
Item data management has encountered structural issues, requiring separations between metadata, properties, and display information. Each category should be used differently based on contextual needs. For example, descriptionsshould be recognized as part of display information, rather than intrinsic item metadata. They were originally not clear for their categories.
Some item attributes may be hardcoded, while others would be dynamically assigned. Internal attributes would be categorized as item properties, whereas externally accessible attributes would be classified as item tags. Both properties and tags may be static or dynamic, depending on their intended behavior.
Tiles should incorporate structured lists of properties, including but not limited to:
- Flammability
- Material type
- Hardness
- Blast resistance
- Luminosity
Tile metadata and models should remain independent of tile positions,
ensuring proper decoupling. The current handling of tile variants within
DirtTile
does not adhere to this principle and requires revision.
If a new food system incorporating various recipes is introduced, materials should maintain minimal attribute definitions, given their shared item-type similarities. Consuming food would still deplete stamina, ensuring balance within gameplay mechanics.
Should potion effects be integrated, they should function as universal interfaces applicable to all living mobs. A dedicated registry should store all potion effect types and their handlers, allowing structured public access and customization.
When items are linked via resource keys, manual association of sprites or models for individual items should become unnecessary.
Instead of relying on Tile$Material
, tools should derive behavior
from tile properties rather than being constrained by an enum. Identifiers
should reside in the registry rather than within individual tile instances,
though a resource entry may be returned, containing both the resource
key and object. Other enum-dependent implementations should transition
toward tile properties or metadata, since using enums as function arguments
limits tile variation flexibility.
Using an enum-based approach in DecorTile
provides little
advantage over conventional constructors and fields. Instead, tiles should be
registered as fields, with arguments directly passed into constructors during
initialization.
Current implementations of Tiles
and Items
classes
exhibit low-level, disorganized structures, requiring structural
improvements for maintainability.
If FarmTile
serves merely as a variant of
DirtTile
, their mechanisms could be merged rather than introducing
a separate tile classification. Dirt tiles would dynamically transition into
farmable states based on moisture and nutrient levels, allowing crops to
grow naturally on them. Rather than defining a new tile, crop interactions would
be tied to soil conditions, ensuring a more seamless agricultural system.
No class should extend the core game class TerraModulus
. The
RenderSystem
would exclusively oversee high-level operations,
with UI components delegated to a dedicated manager, such as
UIManager
or MenuManager
. Sprite management should be
merged into the registry system, ensuring unified asset handling. Rendering
performance should be hardware-accelerated, relying on native libraries and APIs,
particularly for physics-based computations. Specifics regarding graphics and
physics implementations will be addressed later. The major render system would
manage the world renderer states, separating UI and world graphics to ensure
clarity and modularity. Various fields should be decoupled accordingly.
The window size would remain dynamic, with no fixed dimensions. Instead of a canvas scale, an adjustable UI scale would be introduced, functioning as a simple multiple of base dimensions, allowing users to modify UI scaling based on window size without storing these preferences. The entire render system would be backed by an optimized rendering engine.
The canvas should be fully occupied, with UI elements such as the status bar, Heads-Up Display (HUD) components (e.g., hot bar, boss bar, debug screen) structured as menu components rather than static overlays. Level rendering should integrate world background and sky rendering as part of comprehensive world rendering.
Fullscreen functionality and screenshot handling should be managed directly within the render system rather than external methods.
The canvas should aggregate rendering results from both UI and world graphics, efficiently processing composited graphical elements. Internally buffered arrays might be employed within the rendering engine, improving performance and consistency.
Rendering queues present a valuable optimization strategy, streamlining render request processing. However, clearing request validation introduces unnecessary overhead. Instead, hidden elements should be skipped within rendering functions, rather than processing functions for rendering requests. Maintaining well-defined responsibilities prevents inefficiencies.
A separate overlay canvas for light rendering should be eliminated, with a
single unified canvas handling all composited graphical elements via the
rendering engine. The current workaround approach in Screen
,
aimed at optimizing rendering, is not the most practical industry standard.
Furthermore, sprite rendering and inverted color line rendering have yet to
capitalize on Graphics2D
optimizations, which could be enhanced
through OpenGL hardware acceleration.
Several menu components require updates, including the hot bar and various menu frames, though these adjustments align with graphics discussions scheduled for later stages.
The rendering system will likely be custom-implemented for optimal compatibility and usability. However, it remains beneficial to explore existing meshing, modeling, or sprite libraries as supplementary tools.
The toggle mechanism for hardware acceleration remains an open question. Under normal circumstances, there should be no need to disable hardware acceleration, but certain edge cases, such as graphics card incompatibility, may require turning it off. If compatibility issues arise before the application fully launches, in-app toggling becomes impractical. Instead, hardware acceleration settings should be configured via launch arguments or managed internally (by detection), preventing post-launch usability issues.
The loading screen and possibly a splash screen may include a hardcoded embedded image within the application. The loading screen would feature a progress bar, initializing full loading of system components in a manner similar to Minecraft: simple, clean, and iconic, after the appearance of the splash screen with a logo. Additionally, customized splash screens could be inserted pre-title screen, or during world initialization phases (early, middle, after).
Initialization timing for tiles, entities, and items remains under discussion, contingent on registry implementation methods. The title screen should appear only after initialization completes, ensuring all essential resources are preloaded. If fullscreen mode is enabled at launch, the window should transition immediately upon initialization, rather than employing a delayed separate switch.
The Font
class might be consolidated within a single package,
likely hidden inside the graphics module. Character mappings (originally as
chars
field) would be fully configurable through asset packs.
Multiple text rendering modes should be available, including plain,
formatted, and pre-styled options.
An optional configuration object, such as FontStyle
, may be
utilized when drawing text, supporting attributes like background color and
foreground color. Features about rendering boundaries should be deprecated,
including horizontal scrolling function. Horizontal scrolling should be
reserved exclusively for animated automatically scrolling text, rather than
general user interactable menu elements.
Text rendering modes could be consolidated into a single configuration attribute, ensuring streamlined customization: plain text remains unstyled, while enabled attributes apply respective formatting styles. The stack-based "redo" mechanism remains excessively complex, warranting removal. Width calculations may leverage advanced looping techniques, eliminating invalid formatting codes from processing logic. A display component architecture may mitigate such issues. Centered text rendering may also be discarded, with paragraph alignment and shadow effects serving as refined alternatives. Current FontStyle implementation is inadequate and could benefit from a transition to UI component-based solutions.
A texture atlas system would be implemented to improve memory efficiency,
particularly in lower-level engines handling many sprites. All textures
would use a shared set of atlases, with new atlases created only when the
existing ones reach capacity. However, sprite dimensions may not always conform
to square proportions or power-of-two sizing, requiring an efficient algorithm.
A useful reference for this approach is
David Colson’s rectangle packing article
. Since most textures will be rectangular or square, all assets should be
fully loaded from relevant asset packs. The MinicraftImage
class
serves as a simplified alternative to existing image handling structures but
may not be used in this framework.
A high-level wrapper would be introduced to manage low-level sprite
instances. When sprites are incorporated into the centralized texture atlas, each
Sprite
should correspond to a data pointer containing
information about pixel locations within the atlas. These references would then
be registered appropriately. Additionally, Px
would be replaced with
OpenGL functionalities, ensuring greater performance and flexibility.
The SpriteAnimation
class should be restructured to function as
animated instances of sprites, storing only a pointer with minimal
additional data. Animated sprites may exist as either UI components or animated
texture segments, following the specification outlined in the asset pack system.
Internally, its current implementation is overly complex, rather than aligning
with external timing mechanisms, animation should operate using a tick counter
within the world ticking function. Borders should not be managed here, but
delegated to a separate layer. Since sprite instances should be recreated rather
than "relinked", the system should undergo a complete redesign for
efficiency.
The codebase currently lacks structure, requiring major improvements.
SpriteManager
should be governed by registries. If skins are
directly managed via accounts, their in-game management should be
simplified, avoiding unnecessary record-based associations. "Missing"
texture management should be handled at a higher level, rather than simple
functions. With a fully implemented texture atlas system, sprite sheets should
no longer require inefficient separate asset loading. The SpriteMeta
structure is redundant and should be discarded and rebuilt. Additionally,
SpriteType
is messy and inefficient, and would function better under
a registry-based approach.
The interaction between Sprites
and SpriteLink
remains
overly convoluted. The logic behind mirroring tiles individually without
considering relative positional adjustments within the sprite system suggests
a lack of proper filtering mechanisms. OpenGL already provides these
functionalities, making a manual extra implementation unnecessary.
The entity rendering process should primarily rely on texture models, though appearance may vary based on entity states and properties. Instead of using method overrides, an external control element should manage state-dependent visual changes. Interactive models should remain distinct, affecting only physics mechanics, while both elements remain stored within entity data. Interactive models should be simpler than texture models, as textures will be preloaded within the atlas system.
Mob sprite compilation should be generalized into standardized models, due to the new texture model system. If mob models follow a consistent framework, there should be no need for separate sprite sets to manage player "carrying" textures. Player rendering would remain straightforward, covering motions and postures such as swimming, item holding, and falling. Item holding visuals should be refined to better distinguish held items, rather than exclusively displaying items when actively in use.
Items are primarily rendered within HUD components or inventory menus, with additional instances appearing as item entities. When rendered within the GUI, supplementary attributes such as durability should be displayed alongside item models. To ensure modular structure, models and GUI rendering functions should be cleanly separated, preventing unnecessary dependencies.
Using ExplosionTileTicker
for animation is inefficient, as
leveraging tiles for extended animations is a fundamentally flawed design.
Given the tile system, where tile ticking is random while tile entity ticking
is regular, introducing transitional tiles disrupts system consistency.
Instead of relying on temporary tile states, particle animations with immediate
tile destruction would maintain structural integrity within the system. As a
result, ExplodedTile
should be removed entirely.
Each particle entity should represent a single sprite unit, ensuring visual
and mechanical consistency. Additionally, particles should not actively interact
with other world objects. TextParticle
, in particular, does not
behave like a particle but rather serves as a distinct visual effect, making
its implementation overly complex for a basic particle system. Likewise,
WaterParticle
is excessively intricate, its code structure could
be simplified significantly if initial velocities were integrated as standard
entity mechanisms.
The glint particle used in WateringCanItem
should be formally
registered rather than arbitrarily managed. Additionally, splashing particles
should be handled within a more generalized framework, preventing fragmented
particle logic. The current implementation of the watering can is close to be
a magical element in the gameplay, thus should be rewritten. The item should
target an area near the player similar to how the particle effect works, rather
than focusing exclusively on the selected tile, ensuring broader interaction
across surrounding tiles.
Darkness rendering should be refined based on light sources and light levelsstored within chunk data. The rendered light intensity would be influenced by the gamma value setting. Mirroring settings of textures could be streamlined into two separate boolean values, while sprite transformations should be handled through alternative methods, such as filtering functions or similar optimizations.
The Lantern
could be considered one of many advanced artificial
light sources. The lighting system requires significant improvement, particularly
in handling light obstruction by objects, which would enhance gameplay
immersion. Currently, the system does not account for blocked light, and
addressing this limitation could make lighting mechanisms more dynamic and
interactive. Additionally, enum-based if-else chains should transition to
switch-case structures if the Java Development Kits (JDK) version is updated,
while Kotlin implementations should utilize when
expressions for
better readability.
World background rendering should be governed by shaders, ensuring that scenery remains dynamic rather than static. Entity rendering distance should be adjustable via client settings, allowing users to configure their viewing range accordingly. Lighting effects, including blending and raytracing, should be processed through shaders, using tile light values as input data. However, entity-based lighting information should remain excluded from mechanical logic, meaning player sight obstruction would not interfere with shader computations.
Resources and assets should no longer be loaded before canvas initialization, but rather loaded simultaneously with vanilla assets.
Resource packs would no longer rely on directory structures, as assets would be categorized separately within the system. Only packs designed for the current application version should be fully supported, with older packs receiving minimal compatibility support where possible. Vanilla assets, if fully configurable, should be bundled into a single package, either embedded within the binary or provided as an external resource, though modifications should be prohibited, ensuring they are only loaded once on startup. Traversing embedded assets manually would no longer be necessary.
The resource pack selection screen would maintain a two-tab structure, unloaded packs on the left and loaded packs on the right. Higher screen resolution eliminates the need to combine both lists into a single view, as that could reduce discoverability. Only brief descriptions of packs should be displayed, avoiding unnecessary detail within the UI. A watcher system should actively monitor all packs, ensuring real-time updates. Upon exiting the pack selection screen, all selected packs should be loaded into memory, though they should remain unlocked, allowing dynamic reloading of all packs except vanilla assets, even when no changes occur within the UI.
When new items are added to the pack list, the selected entry should remain
active but shift accordingly. If an entry is removed, the selection should be
cleared. Entries would not be selected by mouse but hovered; other control
methods would select entries. The file watcher should function as an independent
utility class, not an inner class of the display system. During loading, packs
should be locked, preventing modifications until the process completes. Movement
of packs via keyboard or controller should require the entry to be actively
selected, reinforcing structured navigation. The entry list might use a linked
list. Soft-read locks should secure pack metadata retrieval, ensuring safe
concurrent access. Logo dimensions should remain unrestricted, though optimal
sizing should always be enforced. Stream handling remains low-level, so a better
manager should be made; filtering assets for retrieval should no longer be
necessary since it would no longer contain a directory structure. Only embedded
assets may invoke readStringFromInputStream
, though usage might be
minimized. Metadata structures should transition away from JSON, with asset
content organized across multiple files instead of relying on single metadata
sources.
Initial Pack Loading during Application Startup
- Locate the directory containing packs.
- Match available packs with user preferences.
- Select compatible packs; issue warnings for unsupported versions or missing entries.
- Apply a hard lock on all packs, including vanilla assets.
- Verify vanilla assets via checksum validation; emit errors if inconsistencies arise.
- Load selected packs sequentially into memory.
- Release all loaded packs upon successful completion.
- Finalize initialization.
Pack Reloading after Saving Preferences
- Unload all assets except vanilla assets.
- Identify matching packs and apply hard locks; issue errors if needed.
- If recoverable errors occur, revert to the pack list screen.
- If a pack updates during the process, return to the pack list screen.
- Load selected packs sequentially into memory.
- Release loaded packs.
The built-in loading screen before loading other assets would use embedded assets in the binary. Although vanilla assets are managed differently, their format and specifications should remain consistent with custom packs. The key distinction lies in how the pack manager aligns operations within the standardized system.
Since pack loading requires distinct stages for initialization and configuration, a single pack manager may not suffice. Post-construction initialization is not considered design-safe, requiring multiple utility components to streamline pack management workflows. Individual packs should remain self-contained, ensuring safe execution structures.
All pack loading operations should be handled through a function within the manager system. Skins should be processed separately from other assets. If assets are loaded at a lower level, their processing logic might not reside within the Kotlin part.
Exceptions should be handled at the individual pack level, meaning that strict mode should terminate loading upon encountering errors, while compatible mode should bypass minor exceptions, allowing support for older versions.
The BookDisplay
implementation likely stemmed from previous
attempts to introduce editable books, but text field handling requires
improvement. Further refinements should be discussed separately. Additionally,
books without a title and page count should not be classified as books, meaning
they should never use this class.
The PagedDisplay
class is redundant, as its functionality can be
more effectively replaced by a scroll pane, which offers greater ease of
use. Unless the system explicitly manages book-like content, pages are unnecessary,
making the class unnecessary.
Since books function as items with stored content, translating them dynamically is discouraged, except for special book types. Translation discrepancies between server-side and client-side configurations could lead to inconsistent content display. For game-generated static books (such as "Antidious"), these should be categorized separately from regular book items to enable client-side translation support.
Thus, BookData
should be considered an outdated structure, as static
book content should be managed via assets rather than hardcoded within the code.
In Kotlin, Action
should be replaced with a typealias for the
function type () -> Unit
, declared in the utils file. Similarly,
Condition
could be defined as () -> Boolean
, or enhanced
using a functional interface for additional capabilities. MonoCondition
would be better replaced by Predicate
, improving clarity and modularity.
Dimension
, Insets
, Point
, and
Rectangle
should transition into immutable value classes. These
graphical elements should be encapsulated within a dedicated graphics module,
restricting use to client-side operations. Additional functions should support
transformations and interactions with these classes. Insets
may be
redundant if Dimension
suffices, though certain functionalities
could be directly merged into Rectangle
.
The Ellipsis
class likely functions as a dot-based loading
animation, a format that is rarely used today. Modern UI favors progress bars,
spinners, or more dynamic and informative animations. The dot animation system
should be retired. SequentialEllipsis
seems to loop a single dot,
while SmoothEllipsis
mimics a looping effect similar to a progress
bar. The DotUpdater
updating functions, though varied, lack
significant justification for inclusion and should be reconsidered.
Direction-based positions should follow standardized enum class structures,
supporting configurations with two, four, five, eight, or nine directions.
RelPos
exemplifies a set of nine directional positions in a
rectangle, while border layouts require sets of five directions.
xIndex
and yIndex
should be computed dynamically based
on ordinal
, rather than being explicitly stored. To enhance value
safety, methods such as getPos
should be avoided, with
getOpposite
optimized through switch-case structures in Java or
when
blocks in Kotlin. If anchors must be defined based on
Point
and RelPos
, an Anchor
class should
be introduced. Some classes may support interchanging, while "to"
functions are preferred over "from" functions.
Both Tickable
and ClientTickable
serve no real purpose,
lacking clear functional necessity, and the reason behind this cannot be found.
Direction
represents entity activity directions, but its enum
constraints limit extensibility when additional directional systems are required.
A spherical coordinate-based vector system with unit length definitions would
provide better flexibility for direction systems without a limited set of directions.
Positional coordinates (e.g., x and y) should not be treated as separate parameters, but consolidated into unified structures, particularly when representing vectors or object positions. This ensures a single-point reference model, applicable to simple vectors, tile positions within dimensions, or other models. Returning entries, such as tiles from chunk managers, should yield data objects containing positional references, tile types, and metadata, allowing direct modifications without extra method calls. Entity instantiations and removals may adhere to a similar management approach.
Most functions in MyUtils
can be replaced with helper functions from
existing utility libraries. Any functions explicitly designed for this codebase
should be declared as top-level functions for improved simplicity.
Due to limitations in coordinate system design, Vector2
remains
underutilized in the codebase. Multiple vector classes should be introduced,
accommodating different parameter configurations and vector properties. These
classes should maintain record-class structures with immutable fields or as value
classes, ensuring primitive-like value integrity.
Certain utility classes could be introduced for synchronization. Thread-safe
maps and collections require simplified syntax, resembling Rust’s
Mutex
and ReadWriteLock
implementations. Note that
existing libraries may already have been available for this purpose. A similar
class could be introduced for managing internally held instances, though
ensuring proper design remains the developer’s responsibility.
Toast notifications should replace on-screen notification text, with world events communicated via chat and client-side game events displayed as toasts. Each toast notification should maintain its own defined lifetime, ensuring structured appearance and expiration timing.
The current toast usage hierarchy lacks consistency. AppToast
extends Toast
, yet is handled at the same level as the superclass,
leading to inconsistencies in field usage. Toasts should either be defined as
separate classes or treated as structured subclasses within a unified system,
depending on implementation needs. The behavioral distinctions between toast
categories suggest that a simple classification approach may be not enough.
Application (system) toasts and gameplay toasts share similar structural properties but serve different use cases. Separating them visually by placing application notifications in the bottom-right corner (similar to Windows system notifications) and gameplay notifications in the top-right corner would provide clear distinction and accessibility. Additionally, players should be able to review gameplay notifications via the inventory menu and access application notifications through the pause menu or other non-gameplay screens.
Toast content should support formatted text, allowing bold titles (pre-styled) and detailed descriptions via external functions responsible for formatted output generation. Instance creation may not be overly frequent, permitting full instantiation of frames without singleton constraints.
The toast constructor design should maintain similar parameter structures, with subclasses deciding primary attributes while allowing optional extra parameters. The sprite property should be treated as an abstract property rather than a constructor parameter, enabling consistent code pattern generalization. Toasts should support nullable values for custom rendering, yet favor sprite-based rendering for simplicity. A separate class may be introduced to align both code quality and flexibility of rendering, allowing sprite rendering and advanced animated rendering.
Toast animations could be introduced but require separate discussion regarding
implementation specifics. AchievementUnlockToast
is not optimally
used in its current form, better structural management for content, frame design,
and animation handling should be considered.
All fishing-related code should be contained within the item class, ensuring logical structuring and consistency.
The FishingData
system could be converted into resources linked
via resource keys, streamlining data management. For realism, the fishing line
could have durability, with the potential to break if stretched excessively,
requiring players to replace it. Fishing rods should be restricted to catching
fish rather than other item types while remaining usable anywhere.
ToolType
should transition from an enum-based system to a class
structure, with all instances stored as constants. ToolItem
instances should reference these tool types directly during construction,
avoiding loop-based initialization. The tool type should be stored as an item
property, enhancing modularity.
If tiles incorporate a health system, mining level mechanisms for tools may become obsolete. However, a dual health meter system could be introduced, where using an appropriate tool activates a mining meter, accelerating resource extraction. Additionally, single-action harvesting tools could bypass the mining meter entirely, eliminating the concern altogether.
Tool durability should remain exclusive to item instances, rather than being defined by tool types. Some materials may not have a dedicated tool type, requiring alternative mechanisms for extraction. Attack damage bonuses for tools may be managed via mappings, associating attacker and target attributes before linking them to specific tools. These collections could be registered to the specific tools systematically, ensuring consistency across combat interactions.
The BucketItem
should store fluids rather than tiles, ensuring
alignment with its intended purpose as a liquid container. The concept of a
"hole" tile value is illogical; it should instead be null, emphasizing
the absence of fluid rather than an arbitrary placeholder. Additionally, the
offset
field, once relevant for sprite sheet slicing, has lost
its necessity and can be replaced by ordinal()
for cleaner indexing.
Some systems like plants, should not depend exclusively on tile instances, but
rather on plant class registrations within the game system. This registry-driven
approach allows tiles, items, and other related elements to be registered based
on the core plant classifications. This includes but not limited to trees, crops,
flowers and grass. Given this structure, mechanisms for TreeTile
,
FlowerTile
, and CropTile
should be unified, providing
shared functionality while still allowing specific behaviors per plant type,
such as fertilization.
Both real-life and fantasy plant species could be supported within the system, introducing unique mechanisms like growth, harvesting, nutrition, diseases, and life stages. Examples of fantasy species include heavenly berries and hellish berries. Each plant type should undergo systematic development, ensuring its growth mechanisms align with environmental factors.
The legacy formatted color values are no longer relevant and should not be
maintained. Instead of relying on the tint function, the system should support
expanded predefined colors and alternative utility functions. Formatting codes
should not be handled within Color
, but rather assigned to a
dedicated class responsible for display string formatting or another
appropriate system. Additionally, original format codes may contain control
characters, which cannot be directly typed, limiting their usability.
The limit
function is redundant, as it essentially mirrors the
existing clamp
function, warranting removal. Tinting functions,
along with most related functions, should also be deprecated, though the
lightness calculation method may still be repurposed elsewhere.
The ClothingItem
class has faced long-standing issues, primarily
due to its lack of meaningful functionality. Its mechanisms should undergo a
complete rewrite, aligning with a system similar to Leather Armor in Minecraft,
allowing for greater adaptability and refinement.
The dye system should transition from a limited color selection to a more extensive color range, such as a full 32-bit RGB spectrum. However, dyed objects may present modeling challenges, requiring a blending or color mapping function for proper visualization. A 1-bit image may facilitate tinting textures, using a dedicated tinting function to ensure consistent rendering across different dyed materials.
The canWool
mechanism appears illogical and should be considered
for removal from the game. Replacing wool tiles with carpet tiles may be a
better alternative, ensuring cleaner mechanisms and usability.
The audio system would be redesigned using OpenAL, supporting multiple new features. However, mixing algorithms will be excluded, opting instead for simple additive methods to maintain audio consistency and quality.
- Non-game environments should feature only UI sounds and background music (BGM).
- In-game audio should exclusively originate from world-based sound sources while an additional ambience track may be available for environmental audio like raining, ensuring immersive interactions.
- In-game sound sources should remain unrestricted, while non-game elements should be limited to the two primary sources.
If achievements transition to an account-based system, all related data should be sourced from the server rather than application assets. This setup would resemble Xbox achievements in Minecraft: Bedrock Edition, enhancing cross-device consistency.
To improve code organization, achievement logic and non-UI components should be decoupled from display-related classes, ensuring separation between achievement management and loading mechanisms. Achievement notifications could be redesigned using toast notifications, delivering more streamlined and engaging alerts.
The existing Achievement
unit class is lightweight, containing only
a few fields, while other logic resides within the display class, hindering
clarity. Reorganizing these elements would greatly improve structure and
maintainability.
The quest management system should be separated from QuestsDisplay
,
similar to how advancements were intended to be structured. The quest tree
display is complex, requiring keyboard navigation in keyboard-only mode, with
mouse-based drag controls as an alternative. The components could be linked like
how OSK keys work.
Several methods for node description presentation could be adopted:
- Tooltips displaying descriptions on hover
- A dedicated panel showing hovered-node content
- Selecting a node via click and displaying content in a separate menu
The JSON-formatted data structure of the quest data would no longer be important
when a new data format will be proposed. Entry and menu data synchronization with
internal states should always be preferred over full refreshing of the status and
lists to prevent unnecessary overheads and ensure consistencies and simplicities.
For example, refreshDisplayableQuests
and reloadEntries
should be used upon data loading.
Inner subclasses within Display
subclasses remain overly complex, but
they could be converted into structured submenus.
Quests should not exist as singletons—instead, but structured in series, with individual quests unlocking sequentially. The quest menu layout could display series lists on the left, while the quest tree visualization occupies the right-hand menu. Series descriptions should be positioned either at the top or bottom of the tree layout.
Quests and advancements should remain distinct, as quests rely on a more abstract progression systems than advancements. In abstraction of them, they are called "Progression Systems". Locked quests should always remain hidden to prevent spoilers, while advancements may be selectively obscured based on advancement levels.
The SeriesQuestViewerDisplay
implementation is notably complex.
A configurable shape-drawing component could simplify tree-node visualization,
allowing quest nodes to function as discrete UI components. If geometric shapes
could be defined as components, direct placement within component pools would
remove the need for graphical drawing algorithms, significantly reducing system
complexity. Elements could be aligned as rows and columns.
The quest tree structure should follow a linked list format, eliminating the need for quest relationship mapping, as node-to-node connectivity should be handled within the component instance itself. Auto-scrolling should apply to keyboard and controller users, while mouse-based users can drag the tree view freely.
If a quest manager is instantiated, functions such as
resetGameQuests
and load
should be deprecated, with
saving handled via the world save manager.
A select dropdown should replace separate tabs for unlocked and completed series, allowing users to filter quests by "All," "Unlocked," or "Completed", with an empty right-hand display when no selection is active.
Given shared properties between advancements and quests, a common superclass should be introduced for simplification and structured inheritance. Most modular vanilla components would allow easy toggling by using same public interfaces.
Advancements should be grouped into topic categories, while quests retain series-based organization. Multiple progress trees may exist within a single category or series, ensuring flexible progression tracking.
Progress elements should require both prerequisite elements and completion criteria, ensuring tasks marked as completed remain fulfilled upon later prerequisite unlocking. All elements should form tree-linked structures, with preceding elements acting as unlocking requirements for succeeding tasks.
To streamline structural definitions, JSON should be replaced with more efficient and structural formats, simplifying creation and parsing.
When the preceding elements have already to be completed, the succeeding elements should be unlocked unless they are necessarily hidden; if completing an element requiring completing another element, it should be included as a kind of criteria instead of being a "requirement" as both "criterion" and "requirement" have similar meanings. Also, rewards should be abstract and with a list for each element. Each criterion may follow with description and the boolean value of whether to be visible.
The existing AdvancementTrigger
should be renamed to
AdvancementTracker
, ensuring clarity in role designation.
Trackers should be registered systematically, facilitating progress detection. They should also support anonymous class implementations, where active instances reference both metadata and tracking status, whether global or player-specific.
Trackers should incorporate generic types, reducing verbosity in type checking. Additionally:
-
Rangeable
should be split into Minimum, Maximum, and Range components. -
ItemConditions
should transition from stack-based tracking to count-based evaluation. - No-op conditions and trackers should be removed, with empty conditions used for structure simplification
During the processing of elements, the game should not be saved for progress synchronization. During tracker evaluation, elements should be bundled into record objects, preventing mutual inclusion complexity.
Given the complexity of AdvancementElement
, separating
responsibilities into distinct classes in a separate package would enhance
organization. Recipe-locking functionalities should exist within a public
interface, enabling advancements or other game systems to control recipe
access restrictions. Advancement categories may be user-specific or global,
depending on the nature of the tracked progress.
Unlike advancements, quests may require prerequisites to be unlocked before tracking completing criteria, preventing pre-unlock tracking. However, the quest system should align structurally with the advancement system, as its current format is outdated.
The HowToPlayDisplay
screen may be retained, with key rendering
improved using images, displaying mapped keys rather than textual key names.
Paragraphs should be consolidated into a single translation entry, simplifying
content management, though minor inconsistencies in line breaks may be
unavoidable.
Control schemes should be categorized into three types:
- Keyboard-Only
- Mouse & Keyboard
- Controller-Only
- Controller & Keyboard
Pure controller scheme may not be recommended if controller connection is unstable. If the controller-only option is selected, the keyboard remains unusable even when the controller disconnects, so it is essential to carefully select the options. The order of the names follows the major-first, minor-second pattern. Each keybinding set does not share settings to another scheme.
Each control scheme should feature structured guides, with subtopics categorized under individual control settings. General gameplay guides should be separated from control-specific guidance, while advanced guides may be referenced externally, such as in a wiki. The layout might align with the structure used in Minecraft: Bedrock Edition.
Tutorials should be restructured, merging into the How-To-Play screen or menu-based guides, akin to RimWorld’s guide system. Completion detection should occur in real-time, tracking interactive elements and input events dynamically. Minecraft’s tutorial approach is not applicable here.
In this section, code style is mostly about the Object-Oriented Programming (OOP) practices in Kotlin.
Prefer static fields when runtime lists offer minimal advantages, as static fields can enhance debugging accessibility.
Avoid overly concise code for performance assumptions. Reducing code size does not necessarily improve runtime efficiency, nor does using loops inherently indicate a better or smarter approach.
Constructor parameters should be simplified into abstract properties when applicable.
Not all initializations need to be placed directly in constructors. Factory helper methods can often provide better structuring.
Extra caution is required when dealing with low-level programming, even in Kotlin, to ensure logical correctness without over-reliance on compiler warnings or errors.
When porting lower-level APIs to higher-level components, developers must remain vigilant to prevent overlooking critical details.
Internal logic in utility classes often operates at a lower level, requiring careful adherence to coding best practices.
Resultant syntax should remain idiomatic to Kotlin, leveraging practical code patterns for improved clarity.
Listeners must be properly registered and unregistered when their holders are destroyed or deemed unnecessary.
"Zombie" listeners should be avoided, as they introduce memory leaks and unintended behaviors. Compilers may not be able to check this.
Using try-finally within try-catch blocks can ensure proper listener cleanup.
If a class’s construction is restricted through private or internal constructors, it can be safely marked public. External code cannot instantiate it directly, keeping control within its intended scope.
Some classes serve specific roles within their domain. Even when publicly exposed, they primarily function within their designated boundaries, ensuring their responsibilities remain intact.
When data moves across domains using publicly available class definitions, safety is maintained as long as the system is well-designed. If the original domain constrains data creation, the integrity remains protected even when other domains use the data.
General-purpose functions or constants should be moved outside their class definitions for broader accessibility.
Restrict visibility of specific members to prevent unintended modifications and access that might break mechanisms.
Numerical countdowns should only transition to count-up models when multiple events require tracking.
If an event dominates counter functionality, both countdown (for the event) and count-up (for secondary triggers) may coexist.
Increment/decrement operations should occur at the end of ticking functions, while conditions regarding counters should be processed beforehand.
Singletons should be avoided unless absolutely necessary, as they introduce additional verbosity and unused code overhead.
A single file should contain no more than two levels of inner classes, ensuring better readability, organization, and simplicity of class structures, even preventing unnecessary verbosity.
Classes referenced exclusively by another class within a multi-component package should be nested within their primary referencing class, particularly when thematic consistency applies.
Extension functions should be used thoughtfully, avoiding excessive pollution that negatively affects coding experience.
If inline initialization is enough, fields should be kept inlined rather than delegated to an initialization block.
String keys should be avoided whenever possible. Instead, defined constants or enums should be used to prevent runtime-only errors and potential bugs and reduce unnecessary parsing overhead.
String parsing is error-prone. In fact, when it is possible to use a way to use OOP features such as classes and builders, those should be used instead of string representations, prevent unnecessary parsing overheads and errors, even subtle bugs. This way, compiler may also aid debugging when the OOP way is used.
The Model-View-Controller (MVC) principle is an important pattern to separate responsibilities of different components in the application. For example, the UI instances of settings only view and control the internal setting values of the settings, but are not persistent or acting as container for internal code.
The review of the Minicraft+ codebase serves as the basis for the development of TerraModulus, focusing on both refining the existing project and strategically planning for the new one. The roadmap emphasizes a transition towards a more structured, modular, and efficient architecture.
A key aspect of this direction is a clear separation of concerns, reflected in the proposed
organization of the core
package and input handling. The application framework
will feature a dedicated Main.kt
file for client and server implementations.
The Game
component will be instantiated as TerraModulus
, with
versioning managed through the application profile. Input handling will be streamlined into
distinct classes for key, text, gamepad, and mouse inputs, while controller management will
be handled by a dedicated ControllerManager
.
The user interface will undergo significant enhancements, moving towards a component-based
design similar to AWT or Swing. This will improve code quality and scope management, with
screens and menus managed more effectively. The settings system will be refactored into
a Preferences
system, ensuring settings values are independent of UI components.
Furthermore, the logging system will be transitioned to a different library for improved
idiomatic usage, and the save system will adopt a schema-driven framework to ensure
backward compatibility.
The roadmap also outlines significant advancements in several other areas. Asset and resource management will be modernized to handle game resources more efficiently. Code quality is a central concern, with a drive towards cleaner, more maintainable, and idiomatic Kotlin code. A new framework is being developed to provide a robust foundation for TerraModulus. There is consideration for using Rust for lower-level engine components to potentially enhance performance. A brand new world system is planned, promising more dynamic and engaging environments. Enhancements to physics are also in scope, alongside the ambition to introduce a 3D world. The project aims to leverage more libraries to expand functionalities and features.
World generation will be a major focus, with a shift towards more flexible, customizable, and standardized procedural generation techniques. This includes the use of scripting and custom data formats to allow for extensive control over world generation parameters, features, and structures. The roadmap also addresses the importance of robust error handling, efficient memory management, and a consistent user experience.
Overall, the development roadmap for TerraModulus outlines a comprehensive overhaul of the Minicraft+ codebase, aimed at creating a more maintainable, extensible, and feature-rich game. This involves a focus on improved architecture, UI design, input handling, and world generation, alongside significant advancements in asset management, code quality, and the underlying engine, with an emphasis on modularity, clarity, and adherence to Kotlin's idiomatic principles.