Skip to content

Conversation

@immortius
Copy link
Contributor

@immortius immortius commented Dec 13, 2025

Closes #484
Closes #461
Closes #536

Overview

Introduces three new objectives centered around exploration - closing anomalies, entering rooms and activating objective blocks. Additionally adds a chance for exit portals to spawn in the rift.

Testing Instructions

  • The objective block objective is now the default for new rift keys
  • The kill objective is now added via "death" essence
  • The explore objective is added via "light" essence
  • The anomaly objective is added via "energy" essence
  • Alternatively all objectives can be added via the wotr riftKey objective command.

Framework Changes

  • New objective type: GoalBasedObjective. This uses the same goals as the quest system. To facilitate this goal updates are now broadcast using the GoalEvent.Update event, so they can be subscribed to by both quests and objectives (or other systems in the future). By reusing the goal system it means whenever a new goal type is implemented it can be used by both - with this update for example it is also possible to add quests to close anomalies, visit rooms and activate objective blocks.
  • RiftMapData is a new level attachment for tracking which rooms in the rift have been discovered or visited. This is currently used to drive the explore room objective by tracking when a new room is entered for the first time. It should also prove useful in the future for the rift map display. The RiftMapEvent.RoomFirstVisitedEvent is broadcast from here.
  • Objectives can now provide a list of JigsawListProcessors to add to the rift configuration.
  • Bridged Rift Parameters to Loot Parameters. There is now a loot context parameter for RiftParameterData, and a rift_parameter number provider to get the value from a rift parameter. Additionally added number providers for obtaining rift room and rift structure counts, and math operator providers for combining different loot parameters (currently multiply, sum, ceil, max, and min). This all enables the use of rift information in goals as part of GoalBasedObjectives.
  • RiftFaster: Replaced the string identifier for generatables with a RiftGenerableId record. This is to make it easier to do logic around the identifiers - particularly logic that shouldn't care about the namespace of the generatable (for other mods adding extra pois and such).
  • RiftFaster: added methods for gathering counts of generatables. Noting that ImplementsLegend has suggested future rework to capture this information during generation.

Smaller Changes

  • An event is now broadcast when an anomaly is closed - AnomalyEvent.Closed
  • New block: ObjectiveBlock, which changes state when first activated and sends off a GoalEvent.Update for the ActivateObjectiveGoal.
  • New goal types: ActivateObjective, CloseAnomaly and VisitRoom.
  • The wotr rift roomInfo command is now wotr rift room info, and a wotr rift room anomalyCount command has been added.
  • Mob type is now optional in the KillMobGoal.
  • The NoObjective now renders a simple message when active. The exploration objectives will fall back to this when no targets are available (if there are no anomalies to close/no objective blocks to activate).
  • The old KillObjective type has been removed, with the kill objective now using the GoalBasedObjective type. This means that it displays the specific number of kills required instead of showing a bar.
  • Improved goal checkbox icon
  • ReplaceSingleJigsaw JigsawListProcessor for having a chance to replace a single jigsaw pool in a generatable.
  • FastWeightedList.codecWithSingleAlternative method for providing a codec for a FastWeightedList with support for a single value being provided instead.
  • Added a method to RiftSpaceCorridor to obtain the location of the connected space.
  • Added ConnectedRoomIterator for iterating rooms connected to a room, outwards to a desired depth.

Bug Fixes

  • Crash in RiftConfig#withCustomData when attempting to override an existing entry.
  • Fix forest trial_spawner configuration having an empty entity, causing log spam.

Refactors

  • Moved goals into their own package core.goal, out from core.quest.
  • Further refactoring around goals, such as introducing GoalState and GoalTracker interfaces and simplifying UI element linkage to goals from different contexts.
  • LootContext is now used instead of LootParams for generating goals and rewards. LootParams were frequently being used to generate a LootContext anyway.
  • Renamed RiftDifficultyEvents and RiftEvents to RiftDifficultyEventHandler and RiftEventHandler. I would suggest that a XEventHandler naming pattern for the classes subscribing to events is clearer than the XEvents pattern, as it separates them better from the XEvent naming for classes providing event types.

Implementation Notes

  • The generics around AnomalyTask and AnomalyState are difficult to work with. I've worked around it but noting that these need some refactoring.
  • It would be nice to split out Objective information from RiftData as its own attachment in the future.

@immortius immortius force-pushed the dividesByZero/#484-exploration-objectives branch from f229af1 to eb2f283 Compare December 13, 2025 21:42
@immortius immortius marked this pull request as ready for review December 15, 2025 09:08
Comment on lines 93 to 95
public RiftSpace getSpaceAt(Vec3i pos) {
return getSpaceAt(pos.getX(), pos.getY(), pos.getZ());
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RiftLayout interface has exact same method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it doesn't. It has getChunkSpace, which is more of a getOrCreateSpaceAt.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't notice that the name is different. But this new overload still seems to be unused.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, it ended up unused.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Different types of RiftGeneratable should probably have their own identifier type since each is identified with different information. Builtins usually only need ResourceLocation, but payload templates need ResourceLocation and palette index.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having multiple types adds complexity for no value, particularly because it makes it harder to work with the identifier. Also not clear there is a use case for future variations. I'll at least make index an OptionalInt and change the string representation to not have an index for the built in cases.


@SubscribeEvent
public static void onDiedInRift(RiftEvent.PlayerDied event) {
// TODO: Rather than sending an event, have a registry of GoalTracking providers? Pros, cons
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how much improvement would that change get, but the current state is kinda weird.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave it alone for now then. Would be easier to change after #536

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, I did a rework. GoalTrackers are now looked up using (registerable) lookup functions, and then they can provide a stream of GoalStates of specific types that can be worked with directly rather than passing around update functions.


import java.util.List;

public record MultiplyNumberProvider(List<NumberProvider> values) implements NumberProvider {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm starting to think that maybe we should make a registry for some common math functions and whenever there is datapacking involving math we just make one "math" type that has function property. Or give it expression string to parse.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could change the rift parameters to lean more on the NumberProvider system. Ignoring the name, LootContext is a pretty flexible mechanism for providing context to number generation.

@immortius immortius marked this pull request as draft December 18, 2025 02:28
@immortius immortius marked this pull request as ready for review December 18, 2025 04:52
@mal0ki
Copy link
Contributor

mal0ki commented Dec 20, 2025

I've played with these changes, and they do work as intended. And we did catch a few bugs with it, but that should all be working alright now.
So this is an approval for me (without code review)

mal0ki added a commit that referenced this pull request Dec 23, 2025
refactor: merged rift package into core.rift
refactor: moved goals into their own package
feat: replace kill objective with goal based version
…atterns of jigsaw with a room distance of entrance

refactor: cleanup and comments
feat: room rift count number provider
feat: additional math operator number providers
feat: RiftMapData for tracking rooms discovered/visited
refactor: use ICancellableEvent for GoalEvent.Update
refactor: replaced use of LootParams with LootContext for goal and reward generation
refactor: removed kill objective
refactor: moved goal widgets from quest to goal package
feat: objective block structures
feat: goal based objectives now fall back on the no objective their goals lack targets
feat: exit portals spawn throughout the rift at low probability
fix: corrected room rift counting
feat: recipe update for new objectives
refactor: reduced duplicate code
refactor: improved some naming
refactor: Simplfied hasNext in ConnectedRoomIterator
refactor: Improved RiftGeneratableId
refactor: Moved objective data into its own level attachment
refactor: Reworked goal update handling
refactor: various cleanup to goal handling
fix: Check right level for objective when leaving rift
@immortius immortius force-pushed the dividesByZero/#484-exploration-objectives branch from 29509a9 to b5a0cbe Compare December 23, 2025 21:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refactor: Rift Objective Data as attachment Exploration Objective Add Quantifiable Objective Progress

4 participants