diff --git a/src/components/map/marker/PlayerMarker.vue b/src/components/map/marker/PlayerMarker.vue index d2bf852..90f9f8b 100644 --- a/src/components/map/marker/PlayerMarker.vue +++ b/src/components/map/marker/PlayerMarker.vue @@ -52,6 +52,7 @@ export default defineComponent({ imageSize: componentSettings.value!.imageSize, showHealth: componentSettings.value!.showHealth, showArmor: componentSettings.value!.showArmor, + showYaw: componentSettings.value!.showYaw, pane: 'players', }), diff --git a/src/index.d.ts b/src/index.d.ts index bb93535..fc53793 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -168,6 +168,7 @@ interface LiveAtlasPlayer { sort: number; hidden: boolean; location: LiveAtlasLocation; + yaw?: number; } interface LiveAtlasSortedPlayers extends Array { @@ -325,6 +326,7 @@ interface LiveAtlasPlayerMarkerConfig { imageSize: LiveAtlasPlayerImageSize; showHealth: boolean; showArmor: boolean; + showYaw: boolean; } export type LiveAtlasPlayerImageSize = 'none' | 'small' | 'large' | 'body'; diff --git a/src/leaflet/icon/PlayerIcon.ts b/src/leaflet/icon/PlayerIcon.ts index 2e96219..18acea8 100644 --- a/src/leaflet/icon/PlayerIcon.ts +++ b/src/leaflet/icon/PlayerIcon.ts @@ -31,6 +31,7 @@ export interface PlayerIconOptions extends BaseIconOptions { imageSize: LiveAtlasPlayerImageSize, showHealth: boolean, showArmor: boolean, + showYaw: boolean, } export class PlayerIcon extends Layer implements Icon { @@ -46,6 +47,9 @@ export class PlayerIcon extends Layer implements Icon { private _playerHealth?: HTMLMeterElement; private _playerArmor?: HTMLMeterElement; + private _playerYaw?: HTMLDivElement; + + private _currentYaw = 0; constructor(player: LiveAtlasPlayer, options: PlayerIconOptions) { super(options as LayerOptions); @@ -103,6 +107,14 @@ export class PlayerIcon extends Layer implements Icon { this._playerInfo.appendChild(this._playerArmor); } + if (this.options.showYaw) { + this._container.classList.add('player--yaw'); + + this._playerYaw = document.createElement('div'); + this._playerYaw.className = 'player__yaw'; + this._container.appendChild(this._playerYaw); + } + this._container.appendChild(this._playerInfo); this.update(); @@ -140,5 +152,15 @@ export class PlayerIcon extends Layer implements Icon { this._playerArmor!.hidden = true; } } + + if(this.options.showYaw) { + if(this._player.yaw !== undefined) { + // https://stackoverflow.com/a/53416030 + const delta = ((((this._player.yaw - this._currentYaw) % 360) + 540) % 360) - 180; + + this._currentYaw = this._currentYaw + delta; + this._playerYaw!.style.setProperty('--player-yaw', `${this._currentYaw}deg`); + } + } } } diff --git a/src/leaflet/marker/PlayerMarker.ts b/src/leaflet/marker/PlayerMarker.ts index 004e3b3..62bb7ce 100644 --- a/src/leaflet/marker/PlayerMarker.ts +++ b/src/leaflet/marker/PlayerMarker.ts @@ -24,6 +24,7 @@ export interface PlayerMarkerOptions extends MarkerOptions { imageSize: LiveAtlasPlayerImageSize, showHealth: boolean, showArmor: boolean, + showYaw: boolean, compact: boolean, } @@ -42,6 +43,7 @@ export class PlayerMarker extends Marker { imageSize: options.imageSize, showHealth: options.showHealth, showArmor: options.showArmor, + showYaw: options.showYaw, compact: options.compact, }); diff --git a/src/providers/Pl3xmapMapProvider.ts b/src/providers/Pl3xmapMapProvider.ts index 866da14..60c99b1 100644 --- a/src/providers/Pl3xmapMapProvider.ts +++ b/src/providers/Pl3xmapMapProvider.ts @@ -105,6 +105,7 @@ export default class Pl3xmapMapProvider extends MapProvider { imageSize: images ? (health && armor ? 'large' : 'small') : 'none', showHealth: health, showArmor: armor, + showYaw: true, } } else { worldConfig.components.playerMarkers = undefined; @@ -440,7 +441,8 @@ export default class Pl3xmapMapProvider extends MapProvider { y: 0, z: !isNaN(player.z) ? player.z + 0.5 : 0, world: player.world, - } + }, + yaw: !isNaN(player.yaw) ? parseFloat(player.yaw) + 180 : 0, }); }); diff --git a/src/scss/leaflet/_markers.scss b/src/scss/leaflet/_markers.scss index 0c6d83c..fb440cc 100644 --- a/src/scss/leaflet/_markers.scss +++ b/src/scss/leaflet/_markers.scss @@ -110,6 +110,37 @@ background: url(../assets/images/armor.png) repeat-x left center; } + .player__yaw { + --player-yaw: 0deg; + + position: relative; + transform: rotate(var(--player-yaw)); + transition: 0.1s transform ease-in; + + &, &:after { + position: absolute; + width: 0; + height: 0; + border-style: solid; + border-color: transparent transparent var(--background-marker); + border-width: 0 0.7rem 2.0rem 0.7rem; + } + + &:after { + content: ''; + top: 0.5rem; + left: -0.4rem; + border-width: 0 0.4rem 1.3rem 0.4rem; + border-bottom-color: var(--text-emphasis); + } + + @at-root { + .no-animations .marker.marker--player .player__yaw { + transition: none; + } + } + } + &.marker--compact { .marker__label { background-color: transparent; @@ -137,6 +168,16 @@ border-bottom-width: 0.2rem; } } + + &.player--yaw { + &:before { + content: none; + } + + .marker__label { + margin-left: 1.8rem; + } + } } .marker__label { diff --git a/src/store/mutations.ts b/src/store/mutations.ts index 378e3fb..86f3d63 100644 --- a/src/store/mutations.ts +++ b/src/store/mutations.ts @@ -421,6 +421,7 @@ export const mutations: MutationTree & Mutations = { existing!.uuid = player.uuid; existing!.armor = player.armor; existing!.location = Object.assign(existing!.location, player.location); + existing!.yaw = player.yaw; existing!.hidden = player.hidden; existing!.displayName = player.displayName; existing!.sort = player.sort; @@ -436,6 +437,7 @@ export const mutations: MutationTree & Mutations = { health: player.health, armor: player.armor, location: player.location, + yaw: player.yaw, displayName: player.displayName, sort: player.sort, hidden: player.hidden, diff --git a/src/util/dynmap.ts b/src/util/dynmap.ts index 8784eab..c204bf5 100644 --- a/src/util/dynmap.ts +++ b/src/util/dynmap.ts @@ -183,6 +183,7 @@ export function buildComponents(response: Configuration): LiveAtlasComponentConf imageSize, showHealth: component.showplayerhealth || false, showArmor: component.showplayerhealth || false, + showYaw: false, } break;