issues
Guide for issues
loh-game issues
In @src/systems/ui/xp_drops.rs at line 93, Replace the panic-causing call to
contexts.ctx_mut().expect("No EGui Context") with graceful error handling: call
contexts.ctx_mut(), match or use if let Ok(ctx) = ... to obtain the
egui::Context and on Err(QuerySingleError) perform the same early-return
behavior used elsewhere in this function (e.g., return early or log and return)
so the function does not panic when the EGui context is unavailable; reference
the contexts.ctx_mut() call and the QuerySingleError result type when making the
change.
In @src/systems/ui/pathing_overlay.rs at line 95, Replace the panicking call
contexts.ctx_mut().expect("No Egui Context") with a non-panicking check and skip
rendering when the Egui context is missing: call contexts.ctx_mut(), if it
returns None return early from the system/function (or otherwise skip the
.show(...) block), and if it returns Some(ctx) use that ctx in the .show(...,
|ui| { ... }) invocation so the UI rendering never panics when the context is
unavailable.
Same expect() concern for EGui context.
Both render_minimap and render_world_map use expect() which will panic if no context exists. Consider graceful handling as suggested for plugin_notifications.rs.
♻️ Suggested refactor
- let ctx = contexts.ctx_mut().expect("No EGui Context");
- let Some(ctx) = contexts.ctx_mut() else {
- return;
- }; Also applies to: 137-137
In @src/systems/ui/milestone_notifications.rs at line 91, The milestone
notification code uses contexts.ctx_mut().expect("No EGui Context") which will
panic if the Egui context is missing; change this to a non-panicking guard:
check contexts.ctx_mut() for None and early-return (or skip rendering) so the
system gracefully defers rendering to the next frame instead of crashing—locate
the use of contexts.ctx_mut() and replace the expect call with an if-let or
match that binds ctx when Some and otherwise returns/continues.
In @src/systems/ui/login.rs at line 115, The call to
connect_events.write(ConnectToServerEvent) uses the wrong EventWriter API;
replace the .write(...) invocation with .send(ConnectToServerEvent) on the
EventWriter instance (connect_events) so the ConnectToServerEvent is dispatched
correctly.
In @src/systems/world/resources.rs around lines 87 - 92, The HarvestAttemptEvent
and other event structs are using the nonexistent Message trait and .add_message
API; replace #[derive(Debug, Clone)] with #[derive(Event)] on
HarvestAttemptEvent (and other event structs), remove any manual impl Message
blocks, change all .add_message:: () calls to .add_event:: () and delete any
use bevy::prelude::Message imports so the code uses Bevy 0.17's #[derive(Event)]
- .add_event API consistently.
In @src/systems/ui/login.rs at line 101, The code uses EventWriter::write when
emitting ClientRequestEvent; replace the call to
request_events.write(ClientRequestEvent(data)) with
request_events.send(ClientRequestEvent(data)) so the event is emitted via the
correct EventWriter API (keep the ClientRequestEvent constructor/argument the
same).
In @src/systems/ui/login.rs at line 31, The code currently uses
contexts.ctx_mut().expect("No EGui Context") which will panic if the EGui
context is unavailable; change this to pattern-match the Result and return early
on error, e.g., use let Ok(ctx) = contexts.ctx_mut() else { return; } so the
login UI system (where ctx is used) exits gracefully when the context is missing
instead of panicking.
In @src/systems/ui/hover_text.rs at line 34, The code panics by calling expect()
on contexts.ctx_mut() in the hover text system; change it to gracefully skip
rendering when the Egui context is absent by checking the Option and returning
early (e.g., use if let Some(ctx) = contexts.ctx_mut() or match to only run the
rendering logic when ctx is Some), ensuring the rest of the system continues
without a panic.
In @src/systems/tutorial.rs around lines 512 - 517, Remove the invalid
impl Message for ... blocks for StartTutorialEvent, TutorialStepCompleteEvent,
TutorialCompleteEvent, and SkipTutorialEvent; delete the four impl lines
referencing Message and rely on Bevy's Event system (EventReader/EventWriter) or
proper derives if you intended a deriveable type, ensuring no Message trait
implementations remain in tutorial.rs.In @src/systems/tutorial.rs around lines 496 - 499, The event registration calls
currently use add_message for the tutorial events; replace each
.add_message:: (),
.add_message:: (),
.add_message:: (), and .add_message:: ()
with .add_event::<...>() so the system registers these as events rather than
messages (update the chain where these four entries occur to use .add_event for
each specific event type).
In @src/systems/tutorial.rs around lines 416 - 420, The code uses
add_item_events.write(...) but EventWriter requires .send(...); replace the
.write call with add_item_events.send(AddItemEvent { entity: event.player, item:
item_id(&item_reward.item_id), quantity: item_reward.quantity as i64 });
ensuring you call send on the add_item_events EventWriter when emitting
AddItemEvent.
In @src/systems/tutorial.rs around lines 368 - 371, The code is calling
EventWriter::write via complete_events.write(...) which is incorrect for Bevy's
EventWriter API; replace the call with
complete_events.send(TutorialCompleteEvent { player: event.player, tutorial_id:
event.tutorial_id.clone() }) so the EventWriter sends the event using send()
instead of write(); update the invocation where TutorialCompleteEvent is
constructed (complete_events) accordingly.
In @src/systems/tutorial.rs around lines 141 - 144, The struct SkipTutorialEvent
lost the Event derive; restore it by adding Event to the derive list for
SkipTutorialEvent (e.g., #[derive(Event, Debug, Clone)]) and ensure the Event
derive macro is in scope by importing the appropriate bevy event derive (e.g.,
bring the bevy Event derive into scope via the existing Bevy prelude or the
correct bevy_ecs_macros import).
In @src/systems/tutorial.rs around lines 135 - 139, The TutorialCompleteEvent
struct lost its Event derive; restore it by changing the derive to include Event
(e.g. #[derive(Debug, Clone, Event)]) on the TutorialCompleteEvent declaration
and ensure the Event derive macro is in scope (import from Bevy prelude or
appropriate crate where Event is defined) so the type is registered as an ECS
event.
In @src/systems/tutorial.rs around lines 128 - 133, The
TutorialStepCompleteEvent struct lost the Event derive; restore it by adding
Event to its derive list for TutorialStepCompleteEvent (e.g., #[derive(Event,
Debug, Clone)]) and, if the Event derive macro is not in scope, import the
appropriate derive (e.g., bring bevy's Event derive into scope via prelude or
the crate that provides it) so the struct is recognized as an event type.
In @src/systems/tutorial.rs around lines 122 - 126, The StartTutorialEvent
struct lost the Event derive; add Event back to its derive list (e.g.,
#[derive(Event, Debug, Clone)] on StartTutorialEvent) and ensure the Event
derive macro is in scope by importing it (for example add use
bevy::prelude::Event or the appropriate bevy event derive import used elsewhere
in the crate).
In @src/systems/player/skills.rs around lines 100 - 103, Remove the invalid Bevy
trait implementation by deleting the lines that implement the nonexistent
Message trait: the two impl Message for XpGainEvent {} and impl Message for
LevelUpEvent {} declarations; ensure no other references to Message remain
(e.g., imports like use bevy::prelude::Message) and run a build to confirm the
compiler no longer expects that trait.
In @src/systems/player/skills.rs around lines 50 - 55, The XpGainEvent struct
lost the Event derive; restore it by adding Event to the derive on XpGainEvent
(e.g., #[derive(Debug, Clone, Event)]) and ensure the Event derive macro is in
scope (import the crate/module that exports the Event derive) so the XpGainEvent
type is recognized as an event by the system.
In @src/systems/player/skills.rs around lines 43 - 44, The code calls
app.add_message:: () and app.add_message:: (), but Bevy
0.17 removed add_message; replace those calls with
app.add_event:: () and app.add_event:: () respectively
so the XpGainEvent and LevelUpEvent are registered correctly with the Bevy App.
In @src/systems/player/inventory.rs around lines 236 - 241, Move the
use bevy::prelude::Message; import from its current location near the bottom of the
file into the module's top-level imports with the other bevy::prelude imports,
then delete the now-duplicate use line that sits directly above the impl Message for AddItemEvent {} / impl Message for RemoveItemEvent {} / impl Message for DropItemEvent {} / impl Message for UseItemEvent {} blocks so
those impls remain unchanged but the import is colocated with other module
imports for clarity.In @src/systems/network/mod.rs around lines 208 - 212, Remove the invalid manual
implementations of the bevy::prelude::Message trait: delete the three impl
blocks "impl Message for ServerMessageEvent {}", "impl Message for
ClientRequestEvent {}", and "impl Message for ConnectToServerEvent {}". If these
event types need to be messages, instead derive or implement the correct
event/message pattern supported by Bevy (e.g., use #[derive(Message)] or
register them as events via App::add_event::<...>()); do not provide empty
manual impls for Message.
In @src/systems/network/mod.rs at line 187, Replace the incorrect EventWriter
call: change the use of events.write(ServerMessageEvent(msg)) to
events.send(ServerMessageEvent(msg)) so the EventWriter API is used correctly;
locate the call that constructs ServerMessageEvent(msg) in the network system
(EventWriter variable named events) and swap .write() for .send().
In @src/systems/network/mod.rs around lines 53 - 55, The code registers events
using add_message; change those calls to add_event for the types
ServerMessageEvent, ClientRequestEvent, and ConnectToServerEvent so the system
uses the correct event registration API: replace
.add_message:: (), .add_message:: (), and
.add_message:: () with .add_event:: (),
.add_event:: (), and .add_event:: ()
respectively.
In @src/systems/network/mod.rs around lines 34 - 35, The ConnectToServerEvent
struct lost the Event derive; restore it by adding the Event derive to the
derive list for ConnectToServerEvent (i.e., change #[derive(Debug, Clone)] to
#[derive(Debug, Clone, Event)]) and ensure the Event derive macro is in scope
(import the appropriate derive macro or module where Event is defined) so the
struct continues to function as an event type.
In @src/systems/network/mod.rs around lines 18 - 19, The struct
ClientRequestEvent lost its Event derive; restore it by adding Event to the
derive list so it reads #[derive(Debug, Event)] for ClientRequestEvent and
ensure the Event derive macro is in scope (import the crate/module that provides
the Event derive, e.g., bring the appropriate bevy/prelude Event derive into
scope) so the compilation and event system integration succeed.
In @src/systems/network/mod.rs around lines 14 - 15, The ServerMessageEvent
struct lost its Event derive; restore it by adding the Event derive alongside
Debug on ServerMessageEvent (i.e., derive Event) and ensure the Event derive
macro is in scope so the type is registered as a Bevy event; update any relevant
imports so the Event derive is available for the ServerMessageEvent struct.
In @src/systems/data/async_loader.rs around lines 550 - 552, Remove the invalid
Message trait impl: delete the block "impl Message for LoadingProgressEvent {}"
and the now-unused "use bevy::prelude::Message;" import (or keep the import only
if used elsewhere) so LoadingProgressEvent is not incorrectly declared as
implementing bevy::prelude::Message.
src/systems/combat/tests.rs
Comment on lines +60 to +61
app.add_message:: ();
app.add_message:: ();
@coderabbitai
coderabbitai bot
8 minutes ago
⚠️ Potential issue | 🟡 Minor
🧩 Analysis chain
Use EventReader/EventWriter in tests for consistency with production code.
Tests register events with add_message:: () but dispatch via manual send_event() and read using Events ::get_reader() (lines 67, 79, 90-92). Production code in mod.rs uses EventReader/EventWriter system parameters. Refactor tests to use the same system parameter pattern for consistency.
Also applies to: line 100, 133-135
In @src/systems/combat/passives.rs around lines 249 - 252, The Message import is
placed at the bottom next to the impls for PassiveTriggerEvent and
StatusExpiredEvent; move the use bevy::prelude::Message line into the module's
top-level import block so it is consolidated with other imports, and then keep
the two impl Message for PassiveTriggerEvent {} and impl Message for
StatusExpiredEvent {} declarations unchanged.
In @src/systems/combat/floating_damage.rs at line 109, Replace the panic-causing
call that forces an Egui context with a graceful early exit: instead of using
let ctx = contexts.ctx_mut().expect("No EGui Context");, check for presence
(e.g., if let Some(ctx) = contexts.ctx_mut() { … } else { return; }) and skip
the floating-damage rendering for that frame when the context is missing; update
any downstream uses of ctx inside the same function/block to be inside the
conditional branch.
In @src/systems/camera/mod.rs at line 179, Replace the panicking expect call on
contexts.ctx_mut() with a defensive pattern: call contexts.ctx_mut() and match
or use if let to handle None, deriving egui_params via ctx.wants_pointer_input()
when Some(ctx) and using a sensible default (e.g., false) or early-return
behavior when None; update the variable egui_params and any downstream logic
that depends on it so it works with the non-panicking branch. Ensure you
reference contexts.ctx_mut(), wants_pointer_input(), and the egui_params
variable when making the change.
In @src/systems/camera/mod.rs around lines 3 - 9, Remove the exploratory
commented-out imports and developer notes in src/systems/camera/mod.rs (e.g.,
the commented lines referencing use bevy::render::primitives::Aabb and use
bevy::render::view::Visibility and the surrounding notes); leave only the actual
needed imports and, if Aabb or Visibility are required, replace the commented
attempts with the correct imports (e.g., use bevy::render::mesh::Aabb or use
bevy::prelude::Visibility) or a single TODO comment with a ticket reference — do
not keep the failed/import trial comments or developer notes in the file.
In @src/systems/audio/sfx.rs around lines 66 - 70, Move the use
bevy::prelude::Message; import up into the module's top import block alongside
the other use statements for consistency; update src/systems/audio/sfx.rs so
Message is imported before the impl Message for PlaySfxEvent {} declaration
(referencing the PlaySfxEvent type and the impl Message block) to keep imports
organized.
In @src/systems/analytics/mod.rs around lines 52 - 54, Replace the generic
window query and iterator usage with Bevy 0.17's PrimaryWindow pattern: change
the query type to Query<&Window, With > (or use &mut Window if you
need mutability) and replace the windows.iter().next() logic with
windows.get_single() (handling the Result/Option it returns) so the system
explicitly requests the primary window; update any variable names that reference
windows to reflect the single primary window (e.g., window) and handle the
err/none case similarly to the previous early return.In @src/plugin_api/bevy_plugin.rs around lines 462 - 466, Replace the incorrect
EventWriter call using interaction_events.write(...) with the proper send API:
call interaction_events.send(...) passing the constructed
crate::systems::api::InteractionEvent { source: player_entity, target,
interaction_type: itype } instance; update any surrounding code that assumed
write()’s return to use send() which returns () and ensure the symbol
interaction_events (the EventWriter) is used with .send rather than .write.
In @src/plugin_api/bevy_plugin.rs around lines 280 - 281, Remove the stray debug
println in the process_automation_commands path: delete the line printing
"DEBUG: process_automation_commands skipping - Player query failed." and replace
it with no output (or a proper logging call if necessary) so that the function
no longer emits a debug STDOUT message when the player query fails; locate the
println! in the process_automation_commands function in bevy_plugin.rs and
remove it.
In @src/plugin_api/bevy_plugin.rs at line 91, Remove the loud tick debug print
in tick_plugins_system: delete the println!("DEBUG: tick_plugins_system running.
Player Query Single: {:?}", ...) or replace it with a conditional debug log
(e.g., log::debug! / tracing::debug!) or wrap it with a runtime/compile-time
guard such as if cfg!(debug_assertions) { ... } so it no longer floods the
console on every tick; target the println invocation in tick_plugins_system for
the change.
In @migrate_events.py around lines 51 - 57, The current derive-replacement logic
can leave stray commas/spaces; update the block that computes new_derives and
replacement_derive to robustly parse the derive list: extract the inner content
from the derives string, split on commas, trim each item, filter out any item
equal to 'Event' or empty, then join with ', ' to form new_derives; if the
filtered list is empty set replacement_derive to the fallback '#[derive(Debug,
Clone)]', otherwise set replacement_derive = f'#[derive({new_derives})]'. Use
the existing variables new_derives and replacement_derive to replace the brittle
replaces.
In @migrate_events.py at line 42, Remove the unused variable offset_corrections
from migrate_events.py by deleting the assignment "offset_corrections = 0" (and
any other unused occurrences of offset_corrections) so there are no dead
variables; if the variable was intended for future logic, either implement that
logic in the relevant function or add a clear TODO comment instead of leaving an
unused assignment.
In @Cargo.toml at line 27, The Cargo.toml entry for the big-brain git dependency
is unpinned which breaks reproducible builds; update the big-brain dependency
line in Cargo.toml to reference a specific commit hash or an exact tag (e.g.,
add rev = "COMMIT_HASH" or tag = "vX.Y.Z") instead of the bare git URL, and
verify that the chosen commit/tag is compatible with Bevy 0.17 before committing
the change.
In @client_log.txt around lines 232 - 244, The systems capture_input_metrics,
handle_add_friend, and handle_remove_friend are still using
EventWriter (and send_client_requests uses
EventReader ) while ClientRequestEvent is registered as a
message; replace those EventWriter/EventReader types with
MessageWriter and MessageReader
respectively in the system function signatures and any local variable types,
update the corresponding use/import lines (bring MessageWriter and MessageReader
into scope), and adjust any method calls if needed to the message API so the
systems consume/produce messages instead of events.
In @migrate_events.py around lines 5 - 6, The open call explicitly passes the
'r' mode even though it's the default; change the line using open(filepath, 'r')
in the code that reads file content to simply open(filepath) (e.g., in the block
that assigns content = f.read()) so the explicit 'r' is removed while preserving
the with context and the content = f.read() behavior.
In @migrate_events.py around lines 5 - 6, The open call explicitly passes the
'r' mode even though it's the default; change the line using open(filepath, 'r')
in the code that reads file content to simply open(filepath) (e.g., in the block
that assigns content = f.read()) so the explicit 'r' is removed while preserving
the with context and the content = f.read() behavior.
The .send() → .write() replacement is overly aggressive.
The regex (\w+events?|writer).send( may incorrectly replace .send() calls on non-EventWriter types (e.g., channel senders, custom types with "events" in their name).
Consider removing this automatic replacement and relying on compiler errors to guide manual fixes, or use a more targeted pattern.
In @migrate_events.py around lines 99 - 103, The for-loop over os.walk uses an
unused variable named dirs; rename it to _dirs in the loop header (for root,
_dirs, files in os.walk("src")) to indicate it's intentionally unused and avoid
linter warnings, leaving the rest of the logic (calling
migrate_file(os.path.join(root, file)) and incrementing files_changed)
unchanged.
In @README.md around lines 1 - 81, The README has markdown lint issues: add a
blank line before and after each heading (e.g., "# Legends of Hastinapur - Game
Client", "## 📁 Repository Structure", "## 🛠 Prerequisites", "### 1. Rust
Toolchain", etc.), ensure fenced code blocks have a language specifier (use
bash for shell snippets and plaintext or ```text where appropriate) and
are surrounded by blank lines (e.g., the repository structure block, the git
clone snippet, Mold installation, fallback RUSTFLAGS snippet, system
dependencies and run/test examples); update each offending block and heading
accordingly for consistent spacing and language tags.In @src/systems/headless_stubs.rs around lines 29 - 78, The added registrations
using app.add_message:: () are wrong because the event types (e.g.,
NPCInteractionEvent, DropLootEvent, PickupItemEvent, PluginNotificationEvent,
OpenBankEvent, DepositItemEvent, WithdrawItemEvent, PurchaseAttemptEvent,
PurchaseSuccessEvent, PurchaseFailedEvent, ActivatePrayerEvent,
DeactivatePrayerEvent, RestorePrayerEvent, HealEvent, MineRockEvent,
FishCatchEvent, CookSuccessEvent, CookBurnEvent, EatFoodEvent,
SmeltSuccessEvent, SmithSuccessEvent, ChopTreeEvent, SelectSpellEvent,
CastSpellEvent, BrewSuccessEvent, DrinkBrewEvent, PlantSeedEvent,
HarvestPatchEvent, CureDiseaseEvent, ClearPatchEvent) lack the required Message
derive/trait bounds and the rest of the code still uses EventReader/EventWriter
(old Bevy API). Fix by either (A) reverting to the old API: replace
app.add_message:: () with app.add_event:: () so existing
EventReader/EventWriter usages continue to compile, or (B) fully migrate: add
#[derive(Message)] and ensure each event type meets Message: Send + Sync +
'static, then update all EventReader/EventWriter usages across the codebase to
the new message reader/writer APIs; pick one approach and make the matching
changes for all the listed event types referenced in the diff.
In @src/systems/player/interaction.rs around lines 44 - 48, The code mixes
graceful early-return for camera_q (let Some((camera, camera_transform)) =
camera_q.iter().next() else { ... return; }) with a panicking
windows.iter().next().expect("No primary window"); make handling consistent by
replacing the expect on windows with a non-panicking check: attempt
windows.iter().next(), log an informational or error message and return early if
None (similar to the camera check), so the system guarded by is_not_headless
never panics when a window is absent.
Critical: Game logic now runs at frame rate instead of tick rate.
Removing run_if(on_event:: ()) causes tick_movement_system to execute every visual frame rather than once per game tick. This breaks the separation between game logic and visual interpolation:
Path consumption: Entire path processed in a single game tick across multiple frames
Energy depletion: Energy costs deducted at 60+ fps instead of tick rate
Frame-rate dependency: Movement logic now varies with frame rate
The comments suggest migrating to messages, but tick_movement_system (lines 171-199) contains no message/event reader logic. Without gating, the system processes ActivePath entities unconditionally every frame.
In @src/systems/player/prayer.rs around lines 365 - 369, Move the
use bevy::prelude::Message; import up into the file's existing import block with
the other Bevy imports (so it lives alongside other bevy::prelude uses) and
remove the duplicate use near the bottom; keep the three impl Message for ... lines (ActivatePrayerEvent, DeactivatePrayerEvent, RestorePrayerEvent)
unchanged so they reference the globally imported Message.In @src/systems/player/prayer.rs around lines 365 - 369, Move the
use bevy::prelude::Message; import up into the file's existing import block with
the other Bevy imports (so it lives alongside other bevy::prelude uses) and
remove the duplicate use near the bottom; keep the three impl Message for ... lines (ActivatePrayerEvent, DeactivatePrayerEvent, RestorePrayerEvent)
unchanged so they reference the globally imported Message.In @src/systems/scenarios/mod.rs around lines 239 - 245, Move the
bevy::prelude::Message import from the bottom of the file into the top import
block with the other use statements, then relocate the three impl Message blocks
so they directly follow the event struct/type definitions (i.e., immediately
after the StartScenarioEvent/WaveStartedEvent/ScenarioCompletedEvent
declarations) instead of at the end of the file; finally remove the duplicate
impls currently at the bottom (the impl Message for StartScenarioEvent, impl
Message for WaveStartedEvent, impl Message for ScenarioCompletedEvent).
In @src/systems/skills/brewing.rs around lines 486 - 492, Move the
use bevy::prelude::Message; import to the top with other imports, remove the manual
empty impls for BrewAttemptEvent, BrewSuccessEvent, and DrinkBrewEvent, and
instead add #[derive(Message)] to each of those event struct definitions
(BrewAttemptEvent, BrewSuccessEvent, DrinkBrewEvent) so they use the derive
macro idiomatically and avoid the bottom-of-file manual impls.In @src/systems/skills/smithing.rs around lines 382 - 389, The manual impls of
the Message trait are redundant—delete the impl Message for SmeltOreEvent {},
impl Message for SmithItemEvent {}, impl Message for SmeltSuccessEvent {}, and
impl Message for SmithSuccessEvent {} blocks and instead add #[derive(Message)]
to the corresponding event structs (SmeltOreEvent, SmithItemEvent,
SmeltSuccessEvent, SmithSuccessEvent); keep or add use bevy::prelude::Message if
needed and remove the now-unneeded manual impl section.
In @src/systems/social/mod.rs around lines 45 - 47, The code silently drops
serialization errors when calling
serialize_packet(&GamePacket::AddFriendRequest(req)) and similar calls; change
the block that currently does "if let Ok(data) = serialize_packet(...)" to match
on the Result and log the Err (including error details and context like "failed
to serialize AddFriendRequest") before returning/continuing; also resolve the
Message/Event API mismatch by replacing EventWriter with
MessageWriter (or change the registration to .add_event() if
you intend to keep EventWriter) so the writer type matches the .add_message()
registration; apply the same logging + writer-type fix to the other occurrences
mentioned (src/systems/ui/login.rs and src/systems/analytics/mod.rs) and ensure
the log messages include the packet variant and error details for easier
debugging.
In @src/systems/ui/character_creation.rs around lines 111 - 116, The cleanup
loop currently calls commands.entity(entity).despawn() which will orphan child
entities; change both loops to use the recursive despawn API (e.g.,
commands.entity(entity).despawn_recursive()) so that CharacterPreview and its
spawned children (body parts, hair) created by update_character_preview are
removed together; update both uses where you iterate over query and cam_query,
ensuring the CharacterPreview-rooted entities are destroyed with their children.
In @src/systems/ui/character_creation.rs around lines 236 - 239, The code
currently calls commands.entity(entity).despawn() in the model_q loop which will
orphan children created with with_children() (see the body/hair attachments in
the block around lines 249-318); change the removal to recursively remove
descendants—e.g. call the appropriate Bevy API to despawn children as well
(replace despawn() with despawn_recursive() or first call despawn_descendants()
then despawn() depending on your Bevy version) for each entity in the model_q
iterator so parents and their attached children are removed together.
In @src/systems/ui/chat_ui.rs around lines 245 - 247, The call to
CornerRadius::same currently uses an unnecessary cast (8.0 as u8) which
truncates and then converts back; update the egui::Frame::default() chain (the
.corner_radius(...) invocation that follows Color32::from_rgba_unmultiplied) to
pass a float directly (e.g., 8.0) to CornerRadius::same so it uses the expected
Into and remove the cast.
In @src/systems/world/triggers.rs around lines 285 - 289, The implementation of
the Bevy Message trait for TriggerActivatedEvent is correct but the diff
contains extra leading blank lines and an unnecessary comment; clean up by
removing the extraneous empty lines and/or the "Migration: Implement Message for
converted Events" line while keeping the import
use bevy::prelude::Message;
and the impl block impl Message for TriggerActivatedEvent {} intact so the
marker trait remains in place.In @src/systems/ui/xp_drops.rs at line 93, Replace the panic-causing call to
contexts.ctx_mut().expect("No EGui Context") with graceful error handling: call
contexts.ctx_mut(), match or use if let Ok(ctx) = ... to obtain the
egui::Context and on Err(QuerySingleError) perform the same early-return
behavior used elsewhere in this function (e.g., return early or log and return)
so the function does not panic when the EGui context is unavailable; reference
the contexts.ctx_mut() call and the QuerySingleError result type when making the
change.
In @src/systems/ui/tutorial_arrows.rs around lines 142 - 145,
ShowTutorialArrowEvent is consumed via EventReader in spawn_tutorial_arrow but
no longer implements the Event trait; restore the Event derive on the
ShowTutorialArrowEvent struct (i.e., derive Event alongside Debug, Clone) and
remove the redundant impl Message block that was added for it (similar to the
fix for RareDropEvent) so the event type is usable with Bevy's EventReader.
In @src/systems/ui/skills_ui.rs at line 98, Replace the unnecessary float-to-u8
cast in the corner radius call: locate the
.corner_radius(egui::CornerRadius::same(4.0 as u8)) invocation and change it to
use an integer literal accepted by CornerRadius::same, e.g.
.corner_radius(egui::CornerRadius::same(4u8)) or
.corner_radius(egui::CornerRadius::same(4)).
In @src/systems/ui/session_summary.rs around lines 105 - 107, The code uses the
non-public CornerRadius::same API in the frame builder
(.corner_radius(egui::CornerRadius::same(8.0 as u8))) which won't compile;
replace that call with an explicit CornerRadius value such as
.corner_radius(egui::CornerRadius { nw: 8.0, ne: 8.0, sw: 8.0, se: 8.0 }) (use
f32 literals) in src/systems/ui/session_summary.rs and apply the same
replacement for other occurrences across the codebase.
In @migrate_events.py around lines 5 - 6, The open call explicitly passes the
'r' mode even though it's the default; change the line using open(filepath, 'r')
in the code that reads file content to simply open(filepath) (e.g., in the block
that assigns content = f.read()) so the explicit 'r' is removed while preserving
the with context and the content = f.read() behavior.
In @client_log.txt around lines 196 - 229, Plugin manifests for
plugins/test_runner, plugins/e2e_skills_test, and plugins/e2e_combat_test are
missing the required author field causing TOML parse/validation failures; open
each plugin's manifest (the [plugin] table) and add an author entry (e.g.,
author = "Your Name") alongside existing name and version keys so the [plugin]
table includes name, version, and author exactly as required.
In @src/systems/ui/chat_ui.rs around lines 284 - 286, The corner_radius call on
egui::Frame::default() uses an unnecessary cast (egui::CornerRadius::same(8.0 as
u8)); remove the cast and pass a float directly (egui::CornerRadius::same(8.0))
so the corner radius uses the correct f32/f64 literal consistently with the
other frame usage.
In @src/systems/skills/mining/mining_tests.rs around lines 111 - 113, The test
currently registers MineRockEvent, AddItemEvent, and XpGainEvent but is marked
#[ignore] claiming E2E coverage that doesn't exist; either implement a mining
E2E test that advances real Time and asserts mining level requirements (create a
test analogous to the other skills' E2E tests that uses the same
Time-advancement helper, fires MineRockEvent, awaits outcomes and verifies level
gating and XP/AddItem behavior for MineRockEvent/AddItemEvent/XpGainEvent), or
update the #[ignore] attribute’s message to honestly state the behavior is
currently untested rather than claiming E2E coverage.
In @src/systems/player/equipment.rs around lines 181 - 186, Move the
bevy::prelude::Message import and the impl Message for EquipItemEvent {} / impl
Message for UnequipItemEvent {} declarations from the bottom of the file to
immediately after the struct definitions for EquipItemEvent and UnequipItemEvent
so the trait impls sit next to their types; then remove the duplicate
import/impls at the file end to avoid redundancy.
In @src/systems/player/combat_interaction.rs around lines 17 - 18, Replace the
panicking .expect() calls on camera_q.iter().next().expect("No camera") and
windows.iter().next().expect("No primary window") with non-panicking early
returns: check for Some(...) using if let or match, optionally log a warning,
and return early from the function (or control flow) when the camera or primary
window is missing so the system won't panic during startup/shutdown or when
resources are temporarily unavailable.
In @src/systems/player/animations.rs around lines 101 - 102, The loop
unnecessarily calls clone() on a Copy type (Entity); remove the redundant clone
by iterating by value instead: replace the pattern "for child in children.iter()
{ let child = child.clone(); ... }" with either "for &child in children.iter() {
... }" or simply "for child in children { ... }" (or "for child in
children.iter().copied() { ... }"), eliminating the explicit clone() call and
keeping the rest of the code using child as before.
In @src/systems/loot/kill_tracker.rs around lines 227 - 231, The migration added
an orphaned import and impl for Message (remove the
use bevy::prelude::Message; and impl Message for RareDropEvent {}) because
RareDropEvent uses #[derive(Event)] and is consumed via EventReader;
delete this migration block so only the #[derive(Event)]-based event type
remains and EventReader usage stays correct.In @src/systems/ui/click_marker.rs at line 53, The call constructs
Quat::from_rotation_x(std::f32::consts::FRAC_PI_2) for every marker; extract
this constant rotation into a local variable (e.g., let ground_rot =
Quat::from_rotation_x(std::f32::consts::FRAC_PI_2)) outside the marker loop and
use ground_rot in the gizmos.circle call (the call invoking
gizmos.circle(Isometry3d::new(pos, Quat::from_rotation_x(...)), ...)) to improve
clarity and avoid repeated construction.
In @src/systems/ui/click_marker.rs around lines 63 - 66, The timer-based despawn
currently checks marker.timer.is_finished() which stays true each frame; change
this to marker.timer.just_finished() so the entity is despawned only on the tick
the timer transitions to finished—update the conditional from
marker.timer.is_finished() to marker.timer.just_finished() where
marker.timer.tick(time.delta()) is called before
commands.entity(entity).despawn().
In @src/systems/ui/combat_ui.rs at line 124, The call to painter.rect_stroke is
incorrectly passing egui::StrokeKind::Middle into Stroke::new; update the
invocation so Stroke::new only receives (width, color) and
egui::StrokeKind::Middle is supplied as the final parameter to rect_stroke —
i.e., locate the painter.rect_stroke(...) call (the one using Stroke::new and
egui::StrokeKind::Middle) and move egui::StrokeKind::Middle out of Stroke::new
into the rect_stroke parameter list while keeping the same width/color
arguments.
In @src/systems/ui/crafting_ui_refactored.rs at line 24, The call
contexts.ctx_mut().expect("No EGui Context") panics if the EGui context is
missing; change it to handle absence gracefully by checking the Option/Result
returned (e.g., if let Some(ctx) = contexts.ctx_mut() { ... } else {
log::warn!("No EGui Context in crafting UI system"); return; }) so the system
returns early instead of panicking; update the variable usage from the existing
ctx expectation to the scoped ctx binding and add a short warning log before
returning.
In @src/systems/ui/friends_ui.rs around lines 187 - 192, The PR mixes Bevy 0.17
event APIs with Cargo set to bevy = "0.15"; pick one target and make the code
consistent: either upgrade to Bevy 0.17 and replace manual impl Message blocks
with #[derive(Message)] on event structs (e.g., AddFriendEvent,
RemoveFriendEvent, AddIgnoreEvent, RemoveIgnoreEvent, SendPrivateMessageEvent,
FriendStatusUpdateEvent), change registrations to use add_message(...) and
consumers like handle_friend_status_updates to use
MessageReader (and update EventReader usages), or stay
on Bevy 0.15 and revert registrations to add_event::<...>() and use
EventWriter/EventReader types throughout (remove add_message usages and the
#[derive(Message)]). Ensure the same event types and reader/writer APIs are used
everywhere (registration, derives/impls, and handle_friend_status_updates).
#[derive(Debug, Clone, Message)]
pub struct AddFriendEvent {
pub name: String,
}
In @src/systems/ui/guard_captain_shop.rs around lines 1 - 8, Remove the
duplicate import and exploratory comment lines: delete the second redundant
use bevy::prelude::*; and remove the commented-out // use bevy::render::camera::Viewport; (and its surrounding notes) so only one use bevy::prelude::*; remains alongside use bevy_egui::{egui, EguiContexts}; and
use std::time::Instant;, keeping imports clean and minimal.In @src/systems/ui/level_up_ui.rs at line 117, Replace the panic-causing call to
contexts.ctx_mut().expect("No EGui Context") with an early return when the Egui
context is missing: call contexts.ctx_mut() (or contexts.try_ctx_mut() if
available) and if it returns None, return early from the function (mirroring the
handling already used around lines 107-115) so the system degrades gracefully
instead of panicking; update the local variable binding to use the Option-unwrap
pattern (if let Some(ctx) = ...) and proceed only when ctx is present.
In @src/systems/ui/music_ui.rs around lines 19 - 27, The system parameters that
currently use EventWriter for message-registered types must be changed to
MessageWriter: replace any function parameters typed as &mut
EventWriter and &mut EventWriter with &mut
MessageWriter and &mut MessageWriter
respectively (e.g., the UI system function in music_ui.rs that writes
SetMusicModeEvent and PlayTrackEvent); also update the corresponding
signatures/usages in the UI module where those same events are written so they
accept and call MessageWriter instead of EventWriter .