Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
171 changes: 171 additions & 0 deletions .github/workflows/check-translations.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
name: Check Translations

on:
pull_request:
paths:
- 'src/main/resources/Server/Languages/**'

jobs:
check-lang-keys:
name: Verify .lang keys
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Check for missing translation keys
run: |
LANG_DIR="src/main/resources/Server/Languages"
EN_DIR="$LANG_DIR/en-US"
EXIT_CODE=0
TOTAL_MISSING=0

if [ ! -d "$EN_DIR" ]; then
echo "::error::No en-US directory found at $EN_DIR"
exit 1
fi

# Collect en-US keys per file
for en_file in "$EN_DIR"/*.lang; do
[ -f "$en_file" ] || continue
filename=$(basename "$en_file")

# Extract keys (non-blank, non-comment lines before '=')
en_keys=$(grep -v '^\s*#' "$en_file" | grep -v '^\s*$' | sed 's/=.*//' | sed 's/\s*$//' | sort)
en_count=$(echo "$en_keys" | wc -l)

# Check each locale
for locale_dir in "$LANG_DIR"/*/; do
locale=$(basename "$locale_dir")
[ "$locale" = "en-US" ] && continue

locale_file="$locale_dir/$filename"

if [ ! -f "$locale_file" ]; then
echo "::error file=$locale_file::[$locale] MISSING FILE: $filename ($en_count keys)"
TOTAL_MISSING=$((TOTAL_MISSING + en_count))
EXIT_CODE=1
continue
fi

# Extract locale keys
locale_keys=$(grep -v '^\s*#' "$locale_file" | grep -v '^\s*$' | sed 's/=.*//' | sed 's/\s*$//' | sort)

# Find missing keys
missing=$(comm -23 <(echo "$en_keys") <(echo "$locale_keys"))

if [ -n "$missing" ]; then
count=$(echo "$missing" | wc -l)
echo "::warning file=$locale_file::[$locale] $filename: $count missing key(s)"
echo "$missing" | while read -r key; do
echo " - $key"
done
TOTAL_MISSING=$((TOTAL_MISSING + count))
EXIT_CODE=1
fi

# Find extra keys (in locale but not in en-US)
extra=$(comm -13 <(echo "$en_keys") <(echo "$locale_keys"))
if [ -n "$extra" ]; then
extra_count=$(echo "$extra" | wc -l)
echo "::notice file=$locale_file::[$locale] $filename: $extra_count extra key(s) not in en-US"
fi
done
done

echo ""
if [ $TOTAL_MISSING -gt 0 ]; then
echo "::error::Total missing keys across all locales: $TOTAL_MISSING"
else
echo "All locales have complete .lang key coverage."
fi

exit $EXIT_CODE

check-help-files:
name: Verify help files
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Check for missing help files
run: |
LANG_DIR="src/main/resources/Server/Languages"
EN_HELP="$LANG_DIR/en-US/help"
EXIT_CODE=0
TOTAL_MISSING=0

if [ ! -d "$EN_HELP" ]; then
echo "::error::No en-US/help directory found at $EN_HELP"
exit 1
fi

# Collect all en-US help file relative paths
en_files=$(cd "$EN_HELP" && find . -name "*.md" -type f | sort)
en_count=$(echo "$en_files" | wc -l)
echo "Found $en_count help files in en-US"

# Check each locale
for locale_dir in "$LANG_DIR"/*/; do
locale=$(basename "$locale_dir")
[ "$locale" = "en-US" ] && continue

locale_help="$locale_dir/help"

if [ ! -d "$locale_help" ]; then
echo "::error file=$locale_help::[$locale] MISSING help/ directory ($en_count files)"
TOTAL_MISSING=$((TOTAL_MISSING + en_count))
EXIT_CODE=1
continue
fi

# Check each en-US help file exists in locale
missing_files=""
missing_count=0
while IFS= read -r relpath; do
locale_file="$locale_help/$relpath"
if [ ! -f "$locale_file" ]; then
missing_files="$missing_files - $relpath"$'\n'
missing_count=$((missing_count + 1))
fi
done <<< "$en_files"

if [ $missing_count -gt 0 ]; then
echo "::error file=$locale_help::[$locale] $missing_count missing help file(s)"
echo "$missing_files"
TOTAL_MISSING=$((TOTAL_MISSING + missing_count))
EXIT_CODE=1
fi

# Check for untranslated files (identical to en-US)
untranslated=0
while IFS= read -r relpath; do
locale_file="$locale_help/$relpath"
en_file="$EN_HELP/$relpath"
if [ -f "$locale_file" ] && cmp -s "$en_file" "$locale_file"; then
untranslated=$((untranslated + 1))
fi
done <<< "$en_files"

if [ $untranslated -gt 0 ]; then
echo "::warning file=$locale_help::[$locale] $untranslated help file(s) identical to en-US (possibly untranslated)"
fi

# Check for extra files not in en-US
if [ -d "$locale_help" ]; then
locale_files=$(cd "$locale_help" && find . -name "*.md" -type f | sort)
extra=$(comm -13 <(echo "$en_files") <(echo "$locale_files"))
if [ -n "$extra" ]; then
extra_count=$(echo "$extra" | wc -l)
echo "::notice file=$locale_help::[$locale] $extra_count extra help file(s) not in en-US"
fi
fi
done

echo ""
if [ $TOTAL_MISSING -gt 0 ]; then
echo "::error::Total missing help files across all locales: $TOTAL_MISSING"
else
echo "All locales have complete help file coverage."
fi

exit $EXIT_CODE
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
.gradle/
build/
!gradle/wrapper/gradle-wrapper.jar
!src/main/java/com/hyperfactions/build/

# IDE
.idea/
Expand Down
120 changes: 120 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,127 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

**Admin GUI: Runtime Config Editor ([#40](https://github.com/HyperSystems-Development/HyperFactions/issues/40))**
- 11-tab config editor covering all HyperFactions settings: Server, Chat, Announcements, Economy, Factions, Faction Perms, Worldmap, Worlds, Backup, Debug, Gravestones
- Size-adaptive layouts: narrow (520px, 1-col), standard (780px, 2-col), wide (1020px, 4-col) — template switches automatically per tab
- Inline editing with boolean toggles, integer/double steppers, text fields, color pickers, enum dropdowns, and locale selectors
- Faction permissions editor with parent/child toggling (disabling parent auto-disables children), Default/Lock checkboxes per flag
- World overrides editor with add/remove worlds and tri-state per-world settings (Default/Allow/Deny)
- Upkeep scaling tiers modal with add/remove/reorder tiers, promote/demote disable on first/last, and live cost example
- Edit session caching — pending changes survive page close/reopen and modal round-trips
- Input validation with per-field error highlighting, debounced text updates, and save-blocked-on-invalid state
- Per-tab label fixes: "Requires Faction", "Show to Factionless", shortened section names
- ConfigSnapshot for applying changes, ConfigValidator for input bounds, ConfigV7→V8 migration

**Admin GUI: Backup Manager ([#41](https://github.com/HyperSystems-Development/HyperFactions/issues/41))**
- Paginated backup list with expand/collapse detail view per entry
- Create manual backups with optional custom name
- Restore backups with two-click confirmation and automatic safety backup
- Delete backups with two-click confirmation
- Backup type filter dropdown (All / Hourly / Daily / Weekly / Manual / Migration)

**Admin GUI: Updates Page ([#42](https://github.com/HyperSystems-Development/HyperFactions/issues/42))**
- Two-column layout: HyperFactions (left) and HyperProtect Mixin (right) with mirrored version info
- Shows current version, latest version, channel, build date, and update status for both
- Single "Check for Updates" button checks both simultaneously
- Download buttons appear when updates are available
- Changelog display for HyperFactions updates
- Rollback support with two-click confirmation
- HyperProtect detection via ProtectionMixinBridge (works even without update checker)

**SimpleClaims Data Importer ([#99](https://github.com/HyperSystems-Development/HyperFactions/issues/99))**
- Import faction claims from SimpleClaims, converting claim data to HyperFactions territory
- Command: `/f admin import simpleclaims [path]`

**FactionsX Data Importer ([#98](https://github.com/HyperSystems-Development/HyperFactions/issues/98))**
- Import faction data from FactionsX, converting factions, claims, and player data
- Command: `/f admin import factionsx [path]`

**World Map Config & BetterMap Compatibility ([#102](https://github.com/HyperSystems-Development/HyperFactions/issues/102))**
- Respect per-world WorldMap enable/disable from world config
- BetterMap integration: compatible with exploration-based map reveal
- Claims and zones render correctly on BetterMap-managed worlds

**Built-in Localization (i18n) ([#92](https://github.com/HyperSystems-Development/HyperFactions/issues/92))**
- 10 languages: en-US, de-DE, es-ES, fr-FR, it-IT, nl-NL, pl-PL, pt-BR, ru-RU, tl-PH
- ~467 translation entries per locale covering all commands, GUI labels, help content
- Player language detection with configurable default and per-player override
- Markdown-based help content system with translation guide

**Split MessageKeys into Domain-Specific Files**
- Split the monolithic `MessageKeys.java` (2,789 lines, 60 inner classes, ~1,298 constants) into 6 focused domain files:
- `CommonKeys.java` — shared messages, protection denial, territory notifications, announcements, teleport, chat display
- `CommandKeys.java` — all player command message keys (create, disband, rename, claim, invite, etc.)
- `HelpKeys.java` — help system message keys (166 constants)
- `AdminKeys.java` — admin command responses and navigation labels
- `GuiKeys.java` — faction and shared GUI page keys
- `AdminGuiKeys.java` — admin GUI page keys (613 constants)
- Deleted original `MessageKeys.java`; updated imports across 130+ files

**Localize Remaining Hardcoded Strings**
- Territory display banners (Wilderness, SafeZone, WarZone titles and subtitles) — now localized per-player via `TerritoryInfo.getPrimaryText(PlayerRef)` and `getSecondaryText(PlayerRef)`
- Update notification messages — "new version available", version info, and update instructions now localized
- Player death broadcast location — `"{0} died at ({1}, {2}, {3}) in {4}"` now localized
- ~70 admin handler strings localized across `AdminUpdateHandler`, `AdminZoneHandler`, `AdminMapDecayHandler`, and `AdminDebugHandler` — covers update/mixin/rollback flow, zone display, decay status, and debug headers

**New Translation Entries**
- Added ~467 new entries per locale file across all 10 supported languages (en-US, de-DE, es-ES, fr-FR, it-IT, nl-NL, pl-PL, pt-BR, ru-RU, tl-PH)
- Covers all split key files (help commands, GUI labels, admin GUI) plus newly localized strings

**API Expansion ([#106](https://github.com/HyperSystems-Development/HyperFactions/issues/106))**
- Comprehensive event system: 20 post-events and 11 cancellable pre-events covering all major faction operations
- `Cancellable` interface for pre-events with `setCancelReason()` for custom denial messages
- Language/i18n API methods: `setPlayerLanguage()`, `getPlayerLanguage()`, `getSupportedLocales()`
- Chat color customization API: `setChatColor()`, `setChatColors()`, `getChatColors()`
- Manager accessor methods: `getChatManager()`, `getEconomyAPI()`, `getJoinRequestManager()`
- Extended query methods: `getFactionPowerStats()`, `getFactionClaimCount()`, `getFactionCount()`, `isFactionRaidable()`, `getPlayerRelation()`
- Config persistence API: `ConfigManager.saveConfig()` and `ConfigManager.reloadConfig()`

**HyperEssentials Integration APIs ([#107](https://github.com/HyperSystems-Development/HyperFactions/issues/107))**
- New API methods for essentials integration: `hasFactionHome()`, `getFactionHomeWorld()`, `getFactionHomeCoords()`, `getFactionHomeCooldownRemaining()`, `isZoneFlagAllowed()`
- `ESSENTIALS_BACK` zone flag — controls whether /back teleportation works in zones (defaults to allowed)
- `FactionHomeTeleportEvent` and `FactionHomeTeleportPreEvent` events for home teleport tracking

**Configurable Announcement Colors**
- 7 per-event color settings in `AnnouncementConfig`: `factionCreatedColor`, `factionDisbandedColor`, `leadershipTransferColor`, `overclaimColor`, `warDeclaredColor`, `allianceFormedColor`, `allianceBrokenColor`
- Colors stored in `announcements.json` under a `"colors"` section, loaded/saved with defaults matching previous hardcoded values
- `AnnouncementManager` reads colors from config instead of using hardcoded `broadcastSuccess`/`broadcastError` calls
- Admin GUI: color picker for each event in the Announcements config tab

**Zone & Power Query API Methods**
- `HyperFactionsAPI.getZone(world, chunkX, chunkZ)` — returns the zone at a chunk position
- `HyperFactionsAPI.getZoneByName(name)` — returns zone by name (case-insensitive)
- `HyperFactionsAPI.getAllZones()` — returns all zones as an unmodifiable collection
- `HyperFactionsAPI.getZonesByType(type)` — returns zones filtered by type (SAFE/WAR)
- `HyperFactionsAPI.isHardcoreMode()` — returns whether hardcore power mode is enabled
- `HyperFactionsAPI.getFactionHardcorePower(factionId)` — returns faction's hardcore power pool value

**Per-World Max Claims**
- New `maxClaims` per-world setting in `worlds.json` — limits how many claims a single faction can hold in a specific world
- `null` or `0` = use global limit, `>0` = per-faction per-world hard cap
- Enforced in both `/f claim` and `/f overclaim` flows
- Admin commands: `/f admin world set <world> maxclaims <value>`, supports `default`/`0` to clear
- New `WORLD_MAX_CLAIMS_REACHED` claim result handled in all consumer sites (commands, GUI map, dashboard)
- Localized error messages in all 10 locales

**World Settings API**
- `HyperFactionsAPI.registerWorldSettings(worldKey, settings)` — upsert with persistence, thread-safe
- `HyperFactionsAPI.getWorldSettings(worldName)` — resolved through wildcard pattern matching
- `HyperFactionsAPI.getConfiguredWorldSettings(worldKey)` — exact key match, no pattern resolution
- `HyperFactionsAPI.removeWorldSettings(worldKey)` — removes and persists
- `WorldSettingsResolver` made thread-safe with volatile fields and copy-on-write rebuild

### Changed

**Consolidate Duplicate Message Keys**
- Consolidated ~25 duplicate keys into shared `CommonKeys.Common` constants — bare `NO_PERMISSION`, `Back`, `Cancel`, `Save`, `Clear`, `N/A` duplicates replaced with single shared references
- Added `CommonKeys.Common.NO_DESCRIPTION`, `MEMBER_COUNT`, and `ECONOMY_DISABLED` shared keys, replacing 3 identical copies each
- Command-specific permission messages with unique wording (e.g., "to create factions", "to claim territory") kept as-is

### Fixed
- **Faction claims in water/ocean nearly invisible on world map** — moved claim overlay to render after water/fluid color ([#90](https://github.com/HyperSystems-Development/HyperFactions/issues/90))
- **Water/lava disappears in own faction claim** — fluid spread was incorrectly tied to `fireSpreadAllowed` config, causing all fluid to be removed in claims when fire spread was disabled. Fluid spread in faction claims is now always allowed ([#95](https://github.com/HyperSystems-Development/HyperFactions/issues/95))

## [0.11.1] - 2026-03-11
Expand Down
Loading