A powerful Minecraft plugin addon for Dynmap that automatically detects and visualizes player-created rail networks as tube map-style overlays with full customization support.
- 🔍 Automatic Detection: Scans loaded chunks for rail blocks—no manual waypoint entry required
- 🧠 Smart Clustering: Groups adjacent rails into continuous networks using BFS algorithm with intelligent path-walking
- 🎨 Customizable Colors: TfL London Underground colors by default, with full custom color support per line
- 📍 Station Markers: Create named stations that render as circles on the map
- 🔧 Manual Line Creation: Build custom lines by adding waypoints through commands
- 💾 Data Persistence: Stores lines and stations in JSON with automatic merge on rescan
- 🎯 Duplicate Prevention: Smart merge system prevents overlapping lines when rescanning
- 👥 Granular Permissions: Personal line control, station management, and admin permissions
- 🔌 CoreProtect Integration: Optional filtering by player-placed rails
- ⚡ Performance Optimized: Configurable debug mode and minimum line length filtering
- 📊 Layer Priority: Stations always render above lines for clear visualization
-
Requirements:
- Spigot/Paper 1.21+
- Dynmap plugin
- (Optional) CoreProtect plugin
-
Download the plugin:
- From Github Releases
-
Install:
- Copy
target/dynmap-railways-1.0.0.jarto your server'splugins/folder - Restart your server
- Copy
-
Verify:
- Check logs for "DynmapRailways v1.0.0 enabled!"
- Look for "Railway Lines" and "Railway Stations" in Dynmap layers
Automatically detect rail networks in your world:
/railway scan # Scan all loaded chunks in all worlds
/railway scan <radius> # Scan chunks within radius around you (admin only)What happens during scanning:
- Finds all rail blocks in loaded chunks
- Clusters adjacent rails into connected networks using BFS pathfinding
- Assigns unique short hex IDs (e.g.,
a3f,b2c) - Assigns TfL colors automatically
- Merges with existing lines to prevent duplicates
- Filters out lines shorter than configured minimum (default: 15 blocks)
- Updates Dynmap visualization
View all detected and created lines:
/railway list # Show all lines with IDs, names, block counts, and colors
/railway line list # Same as aboveExample output:
Rail Lines (3):
a3f: Northern Line (245 blocks, #E21836)
b2c: Circle Line (189 blocks, #FFD300)
5d1: My Custom Route (42 blocks, #888888)
Build custom lines by adding waypoints:
/railway line create <name> # Create a new manual line
/railway line addpoint <id> # Add waypoint at your current locationExample workflow:
/railway line create My Express Route
# Output: Created line: My Express Route (ID: a3f)
# Stand at each waypoint location and run:
/railway line addpoint a3f
# Repeat at each location along your routePersonalize your lines:
/railway line color <id> <#hex> # Set custom color (e.g., #FF0000 for red)
/railway line rename <id> <name> # Rename any line
/railway line remove <id> # Delete a lineExamples:
/railway line color a3f #DC241F # Set to red
/railway line rename a3f Northern Line
/railway line remove b2c # Remove a lineMark important locations on your rail network:
/railway station create <name> # Create station at your location
/railway station list # View all stations
/railway station remove <name> # Remove a stationExamples:
/railway station create King's Cross
/railway station create Paddington Station
/railway station list
/railway station remove King's CrossStations render as white circles (customizable in config) on the map.
Administrative tools:
/railway reload # Reload configuration and refresh visualization
/railway debug info # Show debug informationrailway.admin (default: op)
├─ Full control over everything
├─ Can scan for rails
├─ Can edit any line regardless of creator
└─ Inherits all other permissions
railway.line.personal (default: true)
├─ Create manual lines
├─ Edit lines you created
└─ Edit scanned lines where you're majority placer
railway.station (default: true)
└─ Create and manage stations
railway.use (default: true)
└─ Basic command access
| Permission | Default | Description |
|---|---|---|
railway.use |
true | Use basic commands like /railway list |
railway.line.personal |
true | Create and manage your own lines |
railway.station |
true | Create and manage stations |
railway.admin |
op | Full administrative access |
Regular Player (railway.line.personal + railway.station):
- ✅ Create manual lines
- ✅ Customize their own lines (color, rename, addpoint, remove)
- ✅ Create stations anywhere
- ❌ Cannot scan for rails
- ❌ Cannot edit other players' lines
Admin (railway.admin):
- ✅ Everything above, plus:
- ✅ Scan for rails
- ✅ Edit any line
- ✅ Delete any line
- ✅ Full control
Config file: plugins/DynmapRailways/config.yml
# General settings
general:
debug: false # Enable debug logging (default: false)
min-line-length: 15 # Minimum blocks for a line to be saved (default: 15)
# CoreProtect integration
coreprotect:
enabled: true # Enable CoreProtect integration (default: true)
player-placed-only: true # Only render player-placed lines (default: true)
min-age-days: 0 # Minimum age filter in days, 0 = disabled
max-age-days: 0 # Maximum age filter in days, 0 = disabled
ignore-players: [] # List of players to ignore
# Rail line appearance
lines:
width: 3 # Line width in pixels (default: 3)
opacity: 1.0 # Line opacity 0.0-1.0 (default: 1.0)
# Station appearance
stations:
radius: 5.0 # Circle radius in blocks (default: 5.0)
fill-color: "#FFFFFF" # Fill color hex (default: white)
fill-opacity: 0.9 # Fill opacity 0.0-1.0 (default: 0.9)
border-width: 2 # Border width in pixels (default: 2)
border-color: "#000000" # Border color hex (default: black)
border-opacity: 1.0 # Border opacity 0.0-1.0 (default: 1.0)Default TfL London Underground colors:
| Line | Color | Hex |
|---|---|---|
| Bakerloo | Red | #E21836 |
| Central | Black | #000000 |
| Circle | Yellow | #FFD300 |
| District | Green | #00B0F0 |
| H&C | Pink | #EE7C0E |
| Jubilee | Grey | #A0A5A9 |
| Metropolitan | Magenta | #F391A0 |
| Northern | Dark Red | #9B0056 |
| Piccadilly | Blue | #E7A81E |
| Victoria | Light Blue | #00A4EF |
| W&C | Navy | #0019A8 |
Colors cycle automatically for scanned lines. Set custom colors with /railway line color <id> <#hex>.
src/main/java/com/fabianoley/dynmaprailways/
├── DynmapRailways.java # Main plugin class
├── commands/
│ └── RailwayCommand.java # Command handler with permission checks
├── rail/
│ └── RailLine.java # Rail line data model with overlap detection
├── station/
│ └── Station.java # Station data model
├── scan/
│ └── RailScanner.java # BFS clustering algorithm with merge logic
├── map/
│ └── RailwayMapRenderer.java # Dynmap marker rendering with layer priority
├── integration/
│ └── CoreProtectIntegration.java # CoreProtect API wrapper
└── storage/
└── RailwayDataStorage.java # JSON persistence with ID generation
# Clone the repository
git clone <repo-url>
cd DynmapRailways
# Build with Maven
mvn clean package
# Output: target/dynmap-railways-1.0.0.jarRail Clustering Algorithm:
- Uses breadth-first search (BFS) with 6-directional connectivity
- Traces lines from endpoints (1 neighbor) following direction preference
- Handles junctions, curves, and elevation changes
- Prevents diagonal connections for clean tube map rendering
Smart Merge System:
- Validates existing lines (checks if 50%+ rails still exist)
- Detects overlaps (skips new lines with >70% overlap)
- Prevents duplicate lines when rescanning
- Preserves manual lines and customizations
ID Generation:
- Short hex IDs (e.g.,
a3f,5d1a) - Starts at 3 characters, grows if collisions occur
- Collision-resistant up to 8 characters (268M combinations)
- Deterministic fallback to timestamp hex
Rendering Order:
- Rail lines: Layer priority 5
- Stations: Layer priority 10
- Ensures stations always render above lines
Dynmap API:
- Uses reflection to avoid compile-time dependencies
- Creates separate marker sets for lines and stations
- PolyLineMarkers for rail lines
- CircleMarkers for stations
CoreProtect API:
- Optional integration (enabled in config)
- Filters rails by player who placed them
- Majority vote determines line creator
- Respects player ignore list
Location: plugins/DynmapRailways/
rails.json:
[
{
"id": "a3f",
"name": "Northern Line",
"color": "#E21836",
"blocks": [{"x": 100, "y": 64, "z": 200, "world": "world"}, ...],
"createdBy": "PlayerName",
"createdAt": 1735362000000,
"isActive": true
}
]stations.json:
[
{
"id": "kings_cross",
"name": "King's Cross",
"x": 100,
"y": 64,
"z": 200,
"world": "world",
"createdBy": "PlayerName",
"createdAt": 1735362000000,
"isActive": true
}
]- Build fresh JAR and install on test server
- Create test rail networks with various patterns
- Test scanning:
/railway scan - Verify merging: Rescan to ensure no duplicates
- Test manual lines: Create, add waypoints, customize
- Check permissions: Test with different permission levels
- Validate rendering: Check Dynmap web UI for proper display
Lines not appearing on map:
- Check Dynmap layers panel—ensure "Railway Lines" is enabled
- Run
/railway reloadto refresh visualization - Verify lines exist:
/railway list - Check console for errors during rendering
Duplicate lines after rescanning:
- Ensure you're using the latest version with smart merge
- Lines with <70% overlap are considered unique
- Delete duplicates:
/railway line remove <id>
Permission denied errors:
- Check player has correct permission nodes
- Verify they created the line they're trying to edit
- Admins bypass all ownership checks
CoreProtect integration not working:
- Ensure CoreProtect is installed and enabled
- Check
coreprotect.enabled: truein config - Verify plugin loads after CoreProtect (check plugin.yml softdepend)
Performance issues:
- Enable
general.debug: falseto reduce log spam - Increase
general.min-line-lengthto filter small fragments - Scan smaller areas with
/railway scan <radius>instead of full scan
All rights reserved.
For issues or feature requests, please submit detailed reports including:
- Plugin version
- Server version (Spigot/Paper)
- Dynmap version
- Steps to reproduce
- Expected vs actual behavior
- Console logs (if applicable)
- TfL color palette from London Underground
- Dynmap integration
- CoreProtect integration (optional)