You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
HyperFactions must be compatible with BetterMap (v1.3.3+), a popular world map enhancement mod. Both mods modify world map behavior but through fundamentally different approaches, causing several conflict points that need to be addressed.
Key difference: HyperFactions replaces the entire IWorldMapProvider and IWorldMap generator. BetterMap does NOT replace the provider — it hooks into the existing WorldMapTracker via reflection, modifies WorldMapSettings fields, and sends per-player UpdateWorldMapSettings packets.
Compatibility goals:
HyperFactions' claim overlay rendering should work alongside BetterMap's exploration tracking and fog of war
Map settings (zoom scale, marker creation, teleport flags) should not silently override each other
Player visibility filtering should compose rather than conflict
Both mods' map image quality/scale settings should be reconcilable
HyperFactions should detect BetterMap's presence and adapt behavior accordingly
Reads existing settings and modifies fields via reflection.
Problem: HyperFactions locks scale to 64–128, overriding BetterMap's 10–256 range. BetterMap then tries to modify these values via reflection, but since HyperFactions recreates settings on every getWorldMapSettings() call, BetterMap's modifications may be lost.
Fix: HyperFactions should not hardcode scale values. Either inherit from world config (see #96) or allow config overrides. When BetterMap is detected, defer scale settings to BetterMap.
2. imageScale conflict (HIGH)
HyperFactions: imageScale = 3.0f (very high resolution for claim rendering)
BetterMap: imageScale based on quality (LOW=0.25, MEDIUM=0.5, HIGH=1.0)
BetterMap modifies imageScale via reflection in hookWorldMapResolution()
Whichever runs last wins
Fix: When BetterMap is present, let it control imageScale since it has configurable quality levels. HyperFactions should either detect and defer, or expose its own quality setting.
3. UpdateWorldMapSettings packet race (HIGH)
HyperFactions sends via WorldMapManager.sendSettings() (global broadcast)
BetterMap sends per-player customized packets directly via sendPacket()
BetterMap reads the world's GameplayConfig.WorldMapConfig for canTogglePlayersInMap() and canTrackPlayersInCompass() — HyperFactions ignores these
Last sender wins
Fix: HyperFactions should not send its own settings packet when BetterMap is managing per-player settings. Alternatively, read and respect the same GameplayConfig.WorldMapConfig values BetterMap reads.
Fix: These systems should compose. A player hidden by either mod should stay hidden. Ensure HyperFactions' MapPlayerFilterService doesn't re-add players that BetterMap's privacy system removed, and vice versa.
5. Marker creation flags (MEDIUM)
HyperFactions sets ALL allow* flags to false in its settings packet
BetterMap configures allowCreatingMapMarkers from its own config, and reads allowShowOnMapToggle/allowCompassTrackingToggle from the world's gameplay config
HyperFactions' blanket false overrides BetterMap's waypoint-related marker features
Fix: When BetterMap is present, don't override marker creation/toggle flags. Let BetterMap manage these via its own config.
6. Load order sensitivity (MEDIUM)
BetterMap hooks on PlayerReadyEvent → hookWorldMapResolution() modifies settings
HyperFactions registers on PlayerConnectionHandler → registerProviderIfNeeded() replaces generator
If HyperFactions replaces the generator AFTER BetterMap modified settings, BetterMap's changes are lost
If BetterMap hooks AFTER HyperFactions, it modifies HyperFactions' settings (partially working)
Fix: Detect BetterMap at startup. If present, coordinate initialization order. Consider using a shared settings approach where HyperFactions only provides the claim overlay generator while deferring all settings management to BetterMap.
Suggested approach
Detect BetterMap at startup via class loading check (Class.forName("dev.ninesliced.BetterMap")) or manifest dependency check
When BetterMap is detected:
Don't hardcode UpdateWorldMapSettings values — let BetterMap manage the settings packet
Don't override imageScale — let BetterMap's quality system control it
Still register HyperFactionsWorldMap as generator (claim overlays are needed)
Ensure MapPlayerFilterService composes with BetterMap's privacy system
These should be grantable through HyperPerms when both mods are present.
Risks and Alternatives
Risk: BetterMap may update its internal structure, breaking reflection-based detection. Use class-level detection rather than method-level.
Risk: Load order is not guaranteed. Both mods use PlayerReadyEvent — may need EventPriority to ensure correct ordering.
Challenge: BetterMap's per-player settings (individual zoom scales) conflict with any global settings HyperFactions sends. May need to defer all UpdateWorldMapSettings sending to BetterMap.
Alternative: Instead of auto-detection, require explicit config flag (betterMapCompat: true) — simpler but worse UX.
Alternative: Long-term, BetterMap could integrate with HyperFactions' API for faction-aware exploration (e.g., faction territory already explored for members). This would be a deeper integration beyond basic compatibility.
Scope
HyperFactions must be compatible with BetterMap (v1.3.3+), a popular world map enhancement mod. Both mods modify world map behavior but through fundamentally different approaches, causing several conflict points that need to be addressed.
Key difference: HyperFactions replaces the entire
IWorldMapProviderandIWorldMapgenerator. BetterMap does NOT replace the provider — it hooks into the existingWorldMapTrackervia reflection, modifiesWorldMapSettingsfields, and sends per-playerUpdateWorldMapSettingspackets.Compatibility goals:
Implementation Details
Conflict Analysis
1. WorldMapSettings ownership (CRITICAL)
HyperFactions (
HyperFactionsWorldMap.getWorldMapSettings()):Creates fresh settings from scratch with hardcoded values.
BetterMap (
WorldMapHook.updateWorldMapConfigs()):Reads existing settings and modifies fields via reflection.
Problem: HyperFactions locks scale to 64–128, overriding BetterMap's 10–256 range. BetterMap then tries to modify these values via reflection, but since HyperFactions recreates settings on every
getWorldMapSettings()call, BetterMap's modifications may be lost.Fix: HyperFactions should not hardcode scale values. Either inherit from world config (see #96) or allow config overrides. When BetterMap is detected, defer scale settings to BetterMap.
2. imageScale conflict (HIGH)
imageScale = 3.0f(very high resolution for claim rendering)imageScalebased on quality (LOW=0.25, MEDIUM=0.5, HIGH=1.0)imageScalevia reflection inhookWorldMapResolution()Fix: When BetterMap is present, let it control
imageScalesince it has configurable quality levels. HyperFactions should either detect and defer, or expose its own quality setting.3. UpdateWorldMapSettings packet race (HIGH)
WorldMapManager.sendSettings()(global broadcast)sendPacket()GameplayConfig.WorldMapConfigforcanTogglePlayersInMap()andcanTrackPlayersInCompass()— HyperFactions ignores theseFix: HyperFactions should not send its own settings packet when BetterMap is managing per-player settings. Alternatively, read and respect the same
GameplayConfig.WorldMapConfigvalues BetterMap reads.4. Player visibility overlap (MEDIUM)
MapPlayerFilterService— faction-based filtering (own, ally, enemy, neutral, factionless)MapPrivacyManager+PlayerRadarManager— config-based hiding (hidePlayersOnMap, per-player privacy)WorldMapManagerFix: These systems should compose. A player hidden by either mod should stay hidden. Ensure HyperFactions'
MapPlayerFilterServicedoesn't re-add players that BetterMap's privacy system removed, and vice versa.5. Marker creation flags (MEDIUM)
allow*flags tofalsein its settings packetallowCreatingMapMarkersfrom its own config, and readsallowShowOnMapToggle/allowCompassTrackingTogglefrom the world's gameplay configfalseoverrides BetterMap's waypoint-related marker featuresFix: When BetterMap is present, don't override marker creation/toggle flags. Let BetterMap manage these via its own config.
6. Load order sensitivity (MEDIUM)
PlayerReadyEvent→hookWorldMapResolution()modifies settingsPlayerConnectionHandler→registerProviderIfNeeded()replaces generatorFix: Detect BetterMap at startup. If present, coordinate initialization order. Consider using a shared settings approach where HyperFactions only provides the claim overlay generator while deferring all settings management to BetterMap.
Suggested approach
Class.forName("dev.ninesliced.BetterMap")) or manifest dependency checkUpdateWorldMapSettingsvalues — let BetterMap manage the settings packetimageScale— let BetterMap's quality system control itHyperFactionsWorldMapas generator (claim overlays are needed)MapPlayerFilterServicecomposes with BetterMap's privacy systemworldmap.json→betterMapCompat: "auto"(auto-detect, always, never)BetterMap permission nodes (for reference)
BetterMap uses
PermissionsModuledirectly (not HyperPerms). Key permissions:bettermap.admin— admin accessbettermap.command.teleport— waypoint teleportbettermap.command.waypoint.global— global waypointsbettermap.command.config— config accessbettermap.command.override.*— privacy overrides (players, warps, poi, spawn, death, waypoints)These should be grantable through HyperPerms when both mods are present.
Risks and Alternatives
PlayerReadyEvent— may needEventPriorityto ensure correct ordering.UpdateWorldMapSettingssending to BetterMap.betterMapCompat: true) — simpler but worse UX.References and Media
resources/mods/decompiled/BetterMap/(123 Java files)resources/mods/unpacked/BetterMap/resources/docs/BetterMap/WorldMapService.java:91-124— HyperFactions provider registrationHyperFactionsWorldMap.java:57-63— hardcoded settingsWorldMapHook.java:1060-1084—updateWorldMapConfigs()reflection modificationsWorldMapHook.java:1097-1130—sendMapSettingsToPlayer()per-player packetsExplorationListener.java:71-153—onPlayerReady()hook initialization