{"id":26865809,"url":"https://github.com/midnighttale/bluemap-external-extender","last_synced_at":"2025-08-20T10:05:17.046Z","repository":{"id":259128733,"uuid":"876388016","full_name":"MidnightTale/bluemap-external-extender","owner":"MidnightTale","description":null,"archived":false,"fork":false,"pushed_at":"2024-11-05T03:29:51.000Z","size":52,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-18T17:48:49.114Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MidnightTale.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-10-21T22:13:37.000Z","updated_at":"2025-05-13T06:33:16.000Z","dependencies_parsed_at":"2025-06-18T17:36:29.816Z","dependency_job_id":"8d3f6516-ee1d-453d-aab8-d65476563a92","html_url":"https://github.com/MidnightTale/bluemap-external-extender","commit_stats":null,"previous_names":["midnighttale/midnight-external-extender"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MidnightTale/bluemap-external-extender","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MidnightTale%2Fbluemap-external-extender","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MidnightTale%2Fbluemap-external-extender/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MidnightTale%2Fbluemap-external-extender/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MidnightTale%2Fbluemap-external-extender/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MidnightTale","download_url":"https://codeload.github.com/MidnightTale/bluemap-external-extender/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MidnightTale%2Fbluemap-external-extender/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271299765,"owners_count":24735415,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-20T02:00:09.606Z","response_time":69,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-31T04:44:19.226Z","updated_at":"2025-08-20T10:05:17.040Z","avatar_url":"https://github.com/MidnightTale.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bluemap External Extender\n\nBluemap External Extender is a script that enhances the functionality of BlueMap, allowing for external control and extended features.\n## You can create new entire ui on parent site iframe on like example image \ndemo: [https://mntale.fun/map](https://mntale.fun/map)\n![image](https://github.com/user-attachments/assets/403ae5e6-3803-480d-9f5f-8f07a4e7a2f0)\n![image](https://github.com/user-attachments/assets/9b84a3cb-ae98-4214-83ed-b584c29561e0)\n![image](https://github.com/user-attachments/assets/d252d4fb-f435-4982-9cf4-5d9c78122157)\n\n## Installation\n\n1. Click the \"Code\" button and select \"Download ZIP\".\n2. Extract the ZIP file to your BlueMap web folder (e.g., `bluemap/web/js/`).\n3. Rename the extracted folder to `bluemap-external-extender`.\n4. Edit the BlueMap Web configuration file located at `plugins/BlueMap/webapp.conf`.\n5. Add the Bluemap External Extender script to the `scripts` array:\n\n```\nscripts: [\n  \"js/bluemap-external-extender/main.js\"\n]\n```\n\n6. Save the configuration file and restart your server.\n\n## Post Messages\n\n**Set camera position**\n\n\nCommand: `updatePosition`\nData: `x`, `y`, `z` (number) - camera position in blocks\n\n```javascript\niframeRef.current.contentWindow.postMessage(\n  { \n    type: 'updatePosition', \n    x: 0, \n    y: 64, \n    z: 0 \n  }, \n  '*'\n);\n```\n\n\n**Switch view mode**\n\n\nCommand: `setPerspectiveView`, `setFlatView`, `setFreeFlight`\nOptions: `transition` (number) - transition time in milliseconds\nTransition height: `heightTransition` (number) - transition height in blocks\n\n```javascript\niframeRef.current.contentWindow.postMessage(\n  { \n    type: 'viewMode', \n    command: 'setPerspectiveView', \n    options: { transition: 500, heightTransition: 256 } \n  }, \n  '*'\n);\n```\n\n\n**Follow player**\n\n\nCommand: `followPlayer`\nData: `playerId` (string) - player ID\n\n```javascript\niframeRef.current.contentWindow.postMessage(\n  { \n    type: 'followPlayer', \n    playerId: 'playerId' \n  }, \n  '*'\n);\n```\n\n\n**Update settings**\n\n\nCommand: `updateSettings`\nOptions: `setting` (string) - setting name\n\n- `hiresDistance` (number) - set hires distance\n- `lowresDistance` (number) - set lowres distance\n- `sunlightStrength` (number) - set sunlight strength\n- `ambientLight` (number) - set ambient light strength\n- `pauseTileLoading` (boolean) - set pause tile loading\n- `invertMouse` (boolean) - invert mouse\n- `mouseSensitivity` (number) - set mouse sensitivity\n- `showChunkBorders` (boolean) - set show chunk borders\n- `showDebug` (boolean) - set show debug information\n- `superSampling` (number) - set super sampling value\n- `resetSettings` (boolean) - reset all settings\n  Value: `value` (any) - setting value\n\n```javascript\niframeRef.current.contentWindow.postMessage(\n  { \n    type: 'updateSettings', \n    setting: 'hiresDistance', \n    value: 1000 \n  }, \n  '*'\n);\n```\n\n\n**Teleport to player**\n\n\nCommand: `teleportToPlayer`\nData: `playerId` (string) - player ID\n\n```javascript\niframeRef.current.contentWindow.postMessage(\n  { \n    type: 'teleportToPlayer', \n    playerId: 'playerId' \n  }, \n  '*'\n);\n```\n\n\n**Switch map**\n\n\nCommand: `switchMap`\nData: `mapId` (string) - map ID\n\n```javascript\niframeRef.current.contentWindow.postMessage(\n  { \n    type: 'switchMap', \n    mapId: 'mapId' \n  }, \n  '*'\n);\n```\n\n\n**Reset view**\n\n\nCommand: `resetView`\n\n```javascript\niframeRef.current.contentWindow.postMessage(\n  { \n    type: 'resetView' \n  }, \n  '*'\n);\n```\n\n\n**Animate sunlight strength**\n\n\nCommand: `animateSunlightStrength`\nData: `targetValue` (number) - target value\n\n```javascript\niframeRef.current.contentWindow.postMessage(\n  { \n    type: 'animateSunlightStrength', \n    targetValue: 1 \n  }, \n  '*'\n);\n```\n\n**Get marker list**\n\nCommand: `getMarkers`\n\n```javascript\niframeRef.current.contentWindow.postMessage(\n  { type: 'getMarkers' },\n  '*'\n);\n```\n\n**Toggle marker set visibility**\n\nCommand: `toggleMarkerSet`\nData: `markerSetId` (string) - marker set id\n\n```javascript\niframeRef.current.contentWindow.postMessage(\n  { type: 'toggleMarkerSet', markerSetId: 'markerSetId' },\n  '*'\n);\n```\n\n**Get player list**\n\nCommand: `getPlayerList`\n\n```javascript\niframeRef.current.contentWindow.postMessage(\n  { type: 'getPlayerList' },\n  '*'\n);\n```\n\n**Listen to player list update**\n\nListener: `playerListUpdate`\nData: `players` (string) - player list\n\n```javascript\nwindow.addEventListener('playerListUpdate', (event) =\u003e {\n  const players = JSON.parse(event.data.players);\n  console.log(players);\n});\n```\n\n## Listen Events\n\n**Listen to camera position update**\n\n\nListener: `onPosition`\nData: `x`, `y`, `z` (number) - camera position in blocks\n\n```javascript\nwindow.addEventListener('onPosition', (event) =\u003e \n  {\n  console.log(event.data);\n  }\n);\n```\n\n\n**Listen to view mode change**\n\n\nListener: `onViewMode`\nData: `mode` (string) - view mode\n\n```javascript\nwindow.addEventListener('onViewMode', (event) =\u003e \n  {\n  console.log(event.data);\n  }\n);\n```\n\n\n**Listen to follow player status change**\n\n\nListener: `onFollowingPlayerStatus`\nData: `isFollowing` (boolean) - is following\n\n```javascript\nwindow.addEventListener('onFollowingPlayerStatus', (event) =\u003e \n  {\n  console.log(event.data);\n  }\n);\n```\n\n\n**Listen to map change**\n\n\nListener: `onMapChange`\nData: `mapId` (string) - map ID\n\n```javascript\nwindow.addEventListener('onMapChange', (event) =\u003e \n  {\n  console.log(event.data);\n  }\n);\n```\n\n\n**Listen to url update**\n\n\nListener: `onUrlChange`\nData: `url` (string) - url\n\n```javascript\nwindow.addEventListener('onUrlChange', (event) =\u003e \n  {\n  console.log(event.data);\n  }\n);\n```\n\n**Listen to sunlight strength update (FIRST TIME ONLY)**\n\nListener: `onSunlightStrength`\nData: `value` (number) - sunlight strength\n\n```javascript\nwindow.addEventListener('onSunlightStrength', (event) =\u003e {\n  console.log(event.data);\n});\n```\n\n**Listen to map list update (FIRST TIME ONLY)**\n\nListener: `mapListUpdate`\nData: `mapList` (string) - map list\n```javascript\nwindow.addEventListener('mapListUpdate', (event) =\u003e {\n  console.log(event.data);\n});\n```\n\n**Listen to all settings update (FIRST TIME ONLY)**\n\nListener: `allSettings`\nData: `settings` (string) - settings\n - `hiresSliderMin` (number) - hires slider min\n - `hiresSliderMax` (number) - hires slider max\n - `hiresSliderDefault` (number) - hires slider default\n - `lowresSliderMin` (number) - lowres slider min\n - `lowresSliderMax` (number) - lowres slider max\n - `lowresSliderDefault` (number) - lowres slider default\n - `resolutionDefault` (number) - resolution default\n - `version` (string) - version\n - `maxZoomDistance` (number) - max zoom distance\n - `minZoomDistance` (number) - min zoom distance\n```javascript\nwindow.addEventListener('allSettings', (event) =\u003e {\n  console.log(event.data);\n});\n```\n\n**Listen to localStorage update (FIRST TIME ONLY)**\nListener: `localStorageData`\nData: `storage` (string) - localStorage data\n - `bluemap-superSampling` (number) - super sampling setting\n - `bluemap-mouseSensitivity` (number) - mouse sensitivity setting\n - `bluemap-hiresViewDistance` (number) - high resolution view distance\n - `bluemap-screenshotClipboard` (boolean) - screenshot to clipboard setting\n - `bluemap-pauseTileLoading` (boolean) - pause tile loading setting\n - `bluemap-theme` (string | null) - theme setting\n - `bluemap-lang` (string) - language setting\n - `bluemap-lowresViewDistance` (number) - low resolution view distance\n - `bluemap-tileCacheHash` (number) - tile cache hash\n - `bluemap-chunkBorders` (boolean) - chunk borders display setting\n - `bluemap-resetSettings` (boolean) - reset settings flag\n - `bluemap-debug` (boolean) - debug mode setting\n - `bluemap-showZoomButtons` (boolean) - show zoom buttons setting\n - `bluemap-invertMouse` (boolean) - invert mouse setting\n```javascript\nwindow.addEventListener('localStorageData', (event) =\u003e {\n  console.log(event.data);\n});\n``` \n\n**Listen to marker list update**\n\nListener: `markerListUpdate`\nData: `markers` (string) - marker set and marker data\n\n```javascript\nwindow.addEventListener('markerListUpdate', (event) =\u003e {\n  const markers = JSON.parse(event.data.markers);\n  console.log(markers);\n});\n```\n\n**Update map (reload current map)**\n\nCommand: `updateMap`\n\n```javascript\niframeRef.current.contentWindow.postMessage(\n  { type: 'updateMap' },\n  '*'\n);\n```\n\n**Update theme**\n\nCommand: `updateTheme`\nData: `theme` (string) - theme name ('light', 'dark', 'contrast', etc)\n\n```javascript\niframeRef.current.contentWindow.postMessage(\n  { type: 'updateTheme', theme: 'dark' },\n  '*'\n);\n```\n\n## Additional notes:\n\n- Getting player list with `(map url)/maps/(map id)/live/players.json`\n  Get player list:\n\n```javascript\nconst mapId = 'map id';\nconst mapUrl = 'https://example.com';\nconst fetchPlayers = async () =\u003e {\n  try {\n    const response = await fetch(`${mapUrl}/maps/${mapId}/live/players.json`);\n    const data = await response.json();\n    return data;\n  } catch (error) {\n    console.error('Error fetching players:', error);\n  }\n};\n```\n\nResponse:\n\n```json\n{\n  \"players\": [\n    {\n      \"uuid\": \"playerId\",\n      \"name\": \"playerName\",\n      \"foreign\": playerForeign (boolean),\n      \"position\": {\"x\":playerX,\"y\":playerY,\"z\":playerZ},\n      \"rotation\": {\"pitch\":playerPitch,\"yaw\":playerYaw,\"roll\":playerRoll}\n    },\n    {\n      \"uuid\": \"playerId\",\n      \"name\": \"playerName\",\n      \"foreign\": playerForeign (boolean),\n      \"position\": {\"x\":playerX,\"y\":playerY,\"z\":playerZ},\n      \"rotation\": {\"pitch\":playerPitch,\"yaw\":playerYaw,\"roll\":playerRoll}\n    },\n    ...\n  ]\n}\n```\n\n\n## Getting iframeRef Examples\n\n### React Example\n```jsx\nimport React, { useRef, useEffect } from 'react';\nfunction BlueMapComponent() {\n  const iframeRef = useRef(null);\n  useEffect(() =\u003e {\n    if (iframeRef.current) {\n      // Example: Set camera position\n      iframeRef.current.contentWindow.postMessage(\n        {\n          type: 'updatePosition',\n          x: 0,\n          y: 64,\n          z: 0\n        },\n        ''\n      );\n    }\n  }, []);\n  return (\n    \u003ciframe\n      ref={iframeRef}\n      src=\"https://example.com\"\n      title=\"BlueMap\"\n      width=\"100%\"\n      height=\"600px\"\n    /\u003e\n  );\n}\n\nexport default BlueMapComponent;\n```\n### Normal JavaScript HTML Example\n```html\n\u003chead\u003e\n  \u003cmeta charset=\"UTF-8\"\u003e\n  \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\u003e\n  \u003ctitle\u003eBlueMap Example\u003c/title\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003ciframe id=\"bluemap-iframe\" src=\"https://example.com\" width=\"100%\" height=\"600px\"\u003e\u003c/iframe\u003e\n  \u003cscript\u003e\n    const iframeRef = document.getElementById('bluemap-iframe');\n    // Wait for the iframe to load\n    iframeRef.onload = function() {\n      // Example: Set camera position\n      iframeRef.contentWindow.postMessage(\n        {\n          type: 'updatePosition',\n          x: 0,\n          y: 64,\n          z: 0\n        },\n        ''\n      );\n    };\n  \u003c/script\u003e\n\u003c/body\u003e\n```\nThese examples show how to get iframe and send messages to iframe.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmidnighttale%2Fbluemap-external-extender","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmidnighttale%2Fbluemap-external-extender","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmidnighttale%2Fbluemap-external-extender/lists"}