Handle hidden/offworld players
- Respect server config for greying out players in other worlds - Always grey out players hidden due to other restrictions - Allow following for hidden players, and show their hidden status on the follow popup
This commit is contained in:
parent
217028e044
commit
b92120e801
@ -43,6 +43,7 @@ function buildServerConfig(response: any): DynmapServerConfig {
|
|||||||
return {
|
return {
|
||||||
version: response.dynmapversion || '',
|
version: response.dynmapversion || '',
|
||||||
allowChat: response.allowwebchat || false,
|
allowChat: response.allowwebchat || false,
|
||||||
|
grayHiddenPlayers: response.grayplayerswhenhidden || false,
|
||||||
chatRequiresLogin: response['webchat-requires-login'] || false,
|
chatRequiresLogin: response['webchat-requires-login'] || false,
|
||||||
chatInterval: response['webchat-interval'] || 5,
|
chatInterval: response['webchat-interval'] || 5,
|
||||||
defaultMap: response.defaultmap || undefined,
|
defaultMap: response.defaultmap || undefined,
|
||||||
@ -488,17 +489,20 @@ export default {
|
|||||||
const players: Set<DynmapPlayer> = new Set();
|
const players: Set<DynmapPlayer> = new Set();
|
||||||
|
|
||||||
(response.players || []).forEach((player: any) => {
|
(response.players || []).forEach((player: any) => {
|
||||||
|
const world = player.world && player.world !== '-some-other-bogus-world-' ? player.world : undefined;
|
||||||
|
|
||||||
players.add({
|
players.add({
|
||||||
account: player.account || "",
|
account: player.account || "",
|
||||||
health: player.health || 0,
|
health: player.health || 0,
|
||||||
armor: player.armor || 0,
|
armor: player.armor || 0,
|
||||||
name: player.name ? sanitizer.sanitize(player.name) : "Steve",
|
name: player.name ? sanitizer.sanitize(player.name) : "Steve",
|
||||||
sort: player.sort || 0,
|
sort: player.sort || 0,
|
||||||
|
hidden: !world,
|
||||||
location: {
|
location: {
|
||||||
x: player.x || 0,
|
x: player.x || 0,
|
||||||
y: player.y || 0,
|
y: player.y || 0,
|
||||||
z: player.z || 0,
|
z: player.z || 0,
|
||||||
world: player.world || undefined,
|
world: world,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -232,6 +232,11 @@ export default defineComponent({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(player.hidden) {
|
||||||
|
console.warn(`Cannot follow ${player.name}. Player is hidden from the map.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(!player.location.world) {
|
if(!player.location.world) {
|
||||||
console.warn(`Cannot follow ${player.name}. Player isn't in a known world.`);
|
console.warn(`Cannot follow ${player.name}. Player isn't in a known world.`);
|
||||||
return;
|
return;
|
||||||
|
@ -18,9 +18,12 @@
|
|||||||
<section class="sidebar__section following">
|
<section class="sidebar__section following">
|
||||||
<h2>Following</h2>
|
<h2>Following</h2>
|
||||||
|
|
||||||
<div class="following__target">
|
<div :class="{'following__target': true, 'following__target--hidden': target.hidden}">
|
||||||
<img width="32" height="32" class="target__icon" :src="playerImage" alt="" />
|
<img width="32" height="32" class="target__icon" :src="playerImage" alt="" />
|
||||||
<span class="target__name" v-html="target.name"></span>
|
<span class="target__info">
|
||||||
|
<span class="target__name" v-html="target.name"></span>
|
||||||
|
<span class="target__status" v-show="target.hidden">Currently hidden</span>
|
||||||
|
</span>
|
||||||
<button class="target__unfollow" type="button" :title="`Stop following this player`"
|
<button class="target__unfollow" type="button" :title="`Stop following this player`"
|
||||||
@click.prevent="unfollow"
|
@click.prevent="unfollow"
|
||||||
@keydown="onKeydown">Unfollow</button>
|
@keydown="onKeydown">Unfollow</button>
|
||||||
@ -80,8 +83,22 @@ export default defineComponent({
|
|||||||
right: 1.5rem;
|
right: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.target__name {
|
.target__info {
|
||||||
margin-left: 2rem;
|
margin-left: 2rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
.target__status {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.following__target--hidden {
|
||||||
|
.target__icon {
|
||||||
|
filter: grayscale(1);
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,10 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<li class="player">
|
<li :class="{'player': true, 'player--hidden' : !!player.hidden, 'player--other-world': otherWorld}">
|
||||||
<img width="16" height="16" class="player__icon" :src="playerImage" alt="" />
|
<img width="16" height="16" class="player__icon" :src="playerImage" alt="" />
|
||||||
<button class="player__name" type="button" title="Click to center on player Double-click to follow player"
|
<button class="player__name" type="button" :title="title"
|
||||||
|
:disbled="player.hidden"
|
||||||
@click.prevent="pan"
|
@click.prevent="pan"
|
||||||
@keydown="onKeydown"
|
@keydown="onKeydown"
|
||||||
@dblclick.prevent="follow" v-html="player.name"></button>
|
@dblclick.prevent="follow" v-html="player.name"></button>
|
||||||
@ -45,20 +46,44 @@ export default defineComponent({
|
|||||||
playerImage: playerImage,
|
playerImage: playerImage,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
otherWorld(): boolean {
|
||||||
|
const store = useStore();
|
||||||
|
return store.state.configuration.grayHiddenPlayers
|
||||||
|
&& (!store.state.currentWorld || store.state.currentWorld.name !== this.player.location.world);
|
||||||
|
},
|
||||||
|
title(): string {
|
||||||
|
if(this.player.hidden) {
|
||||||
|
return 'This player is currently hidden from the map\nDouble-click to follow player when they become visible';
|
||||||
|
} else if(this.otherWorld) {
|
||||||
|
return 'This player is in another world.\nClick to center on player\nDouble-click to follow player';
|
||||||
|
} else {
|
||||||
|
return 'Click to center on player\nDouble-click to follow player';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
follow() {
|
follow() {
|
||||||
useStore().commit(MutationTypes.SET_FOLLOW_TARGET, this.player);
|
useStore().commit(MutationTypes.SET_FOLLOW_TARGET, this.player);
|
||||||
},
|
},
|
||||||
pan() {
|
pan() {
|
||||||
useStore().commit(MutationTypes.CLEAR_FOLLOW_TARGET, undefined);
|
if(!this.player.hidden) {
|
||||||
useStore().commit(MutationTypes.SET_PAN_TARGET, this.player);
|
useStore().commit(MutationTypes.CLEAR_FOLLOW_TARGET, undefined);
|
||||||
|
useStore().commit(MutationTypes.SET_PAN_TARGET, this.player);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onKeydown(e: KeyboardEvent) {
|
onKeydown(e: KeyboardEvent) {
|
||||||
if(e.key !== ' ') {
|
if(e.key !== ' ' && e.key !== 'Enter') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
e.shiftKey ? this.follow() : this.pan();
|
if(e.shiftKey) {
|
||||||
|
this.follow();
|
||||||
|
} else {
|
||||||
|
if(!this.player.hidden) {
|
||||||
|
this.pan();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -88,5 +113,26 @@ export default defineComponent({
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.player--hidden {
|
||||||
|
.player__icon {
|
||||||
|
filter: grayscale(1);
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player__name {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.player--other-world {
|
||||||
|
.player__icon {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
12
src/dynmap.d.ts
vendored
12
src/dynmap.d.ts
vendored
@ -57,6 +57,7 @@ interface DynmapServerConfig {
|
|||||||
loginEnabled: boolean;
|
loginEnabled: boolean;
|
||||||
loginRequired: boolean;
|
loginRequired: boolean;
|
||||||
maxPlayers: number;
|
maxPlayers: number;
|
||||||
|
grayHiddenPlayers: boolean;
|
||||||
hash: number;
|
hash: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,11 +170,12 @@ interface DynmapUpdateResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface DynmapPlayer {
|
interface DynmapPlayer {
|
||||||
account: string
|
account: string;
|
||||||
armor: number
|
armor: number;
|
||||||
health: number
|
health: number;
|
||||||
name: string
|
name: string;
|
||||||
sort: number
|
sort: number;
|
||||||
|
hidden: boolean;
|
||||||
location: DynmapLocation;
|
location: DynmapLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,6 +259,7 @@ export const mutations: MutationTree<State> & Mutations = {
|
|||||||
existing!.health = player.health;
|
existing!.health = player.health;
|
||||||
existing!.armor = player.armor;
|
existing!.armor = player.armor;
|
||||||
existing!.location = Object.assign(existing!.location, player.location);
|
existing!.location = Object.assign(existing!.location, player.location);
|
||||||
|
existing!.hidden = player.hidden;
|
||||||
existing!.name = player.name;
|
existing!.name = player.name;
|
||||||
existing!.sort = player.sort;
|
existing!.sort = player.sort;
|
||||||
} else {
|
} else {
|
||||||
@ -269,6 +270,7 @@ export const mutations: MutationTree<State> & Mutations = {
|
|||||||
location: player.location,
|
location: player.location,
|
||||||
name: player.name,
|
name: player.name,
|
||||||
sort: player.sort,
|
sort: player.sort,
|
||||||
|
hidden: player.hidden,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +74,7 @@ export const state: State = {
|
|||||||
loginEnabled: false,
|
loginEnabled: false,
|
||||||
loginRequired: false,
|
loginRequired: false,
|
||||||
maxPlayers: 0,
|
maxPlayers: 0,
|
||||||
|
grayHiddenPlayers: false,
|
||||||
hash: 0,
|
hash: 0,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user