Browse Source

web socket servers

master
gsd 1 year ago
parent
commit
69011ec9b2
  1. 46
      src/api/GlobalApi.js
  2. 30
      src/components/ActionDialogs/ServerStatsDialog.vue
  3. 6
      src/components/ActionDialogs/WorldwideMap.vue
  4. 12
      src/components/TabsMenuElements/ServersView/Components/ServerCard.vue
  5. 28
      src/components/TabsMenuElements/ServersView/Components/ServerFullInfo.vue
  6. 43
      src/components/TabsMenuElements/ServersView/ServersView.vue

46
src/api/GlobalApi.js

@ -19,6 +19,7 @@ export default class GlobalApi {
"e":[],
"n":[]
},
"servers_map":{},
'uniq': {"uniq":{"total":0,"month":0,"year":0,"day":0}},
'builddate':0,
'ban_count':0,
@ -41,7 +42,15 @@ export default class GlobalApi {
load_stages = new Stages();
servers_ws = null;
servers_ws_first_payload = true;
constructor() {
this.servers_ws = new WebSocket("wss://tf2.pblr-nyk.pro/ws/servers")
this.servers_ws.onopen = () => {console.log("[WS] Websocket servers connected")};
this.servers_ws.onmessage = (e) => {
this.update_server(JSON.parse(e.data)["servers"], false);
};
document.title = "Факты 13";
}
@ -55,20 +64,16 @@ export default class GlobalApi {
}
getHumanServerName(server) {
for (const mode in this.stats['servers']) {
for (const srv in this.stats['servers'][mode]) {
if (this.stats['servers'][mode][srv]['key'] === server) return this.stats['servers'][mode][srv]['name'];
}
for (const srv in this.stats.servers_map) {
if (srv['key'] === server) return srv['name'];
}
return "неизвестный";
}
getServers4Selector() {
let r = [];
for (const mode in this.stats['servers']) {
for (const srv in this.stats['servers'][mode]) {
r.push({"srv": this.stats['servers'][mode][srv]['key'], "name": this.stats['servers'][mode][srv]['name']})
}
for (const srv in this.stats.servers_map) {
r.push({"srv": srv['key'], "name": srv['name']})
}
return r;
}
@ -106,6 +111,17 @@ export default class GlobalApi {
})
}
update_server(response, first) {
if (first === true) {
for (let srv in response)
response[srv]['key'] = srv;
this.stats["servers_map"] = response;
} else {
for (let srv in response) {
this.stats["servers_map"][srv] = response[srv];
}
}
}
async fillServers() {
this.load_stages.add("servers")
@ -113,19 +129,7 @@ export default class GlobalApi {
return axios.get("/api/stats?filter=servers" + Random.getRndWebAppend())
.then(response => response.data['servers'])
.then(response => {
let srvs = {
'w':[],
"e":[],
'n':[]
};
for (let srv in response) {
response[srv]['key'] = srv;
if (response[srv]['status'] == false) srvs.n.push(response[srv]);
else if (response[srv]['player_count'] > 0) srvs.w.push(response[srv]);
else srvs.e.push(response[srv]);
}
srvs['w'] = srvs['w'].sort((s1,s2) => s2.player_count - s1.player_count);
this.stats['servers'] = srvs;
this.update_server(response, true);
})
.catch(err => {
console.log(`[API] cannot request servers, err: ${err}`);

30
src/components/ActionDialogs/ServerStatsDialog.vue

@ -20,7 +20,7 @@
<p>Использование памяти: {{docker.mem.percent}}% ({{bytesToHigh(docker.mem.usage)}} / {{bytesToHigh(docker.mem.limit)}})</p>
<p>Всего трафика (rx/tx): {{bytesToHigh(docker.net.input)}} / {{bytesToHigh(docker.net.output)}}</p>
<p>Записи на диск (rx/tx): {{bytesToHigh(docker.io.input)}} / {{bytesToHigh(docker.io.output)}}</p>
<p>Обновленно: {{(new Date(docker.utime * 1000)).toLocaleString()}}</p>
<!--<p>Обновленно: {{(new Date(docker.utime * 1000)).toLocaleString()}}</p>-->
</div>
<hr width="80%">
<div style="padding: 1% 5%; min-width: 400px; max-width: 400px">
@ -42,22 +42,30 @@
<script>
export default {
name: "ServerStatsDialog",
data: () => ({
show: false,
uniq: {"total":0, "month":0, "year":0, "day":0},
props: {
docker: {
"cpu":{"percent":0.0},
"mem":{"percent":0.0, "usage":0, "limit":0},
"io":{"input":0, "output":0},
"net":{"input":0, "output":0}
type: Object,
default: Object.create({
"cpu":{"percent":0.0},
"mem":{"percent":0.0, "usage":0, "limit":0},
"io":{"input":0, "output":0},
"net":{"input":0, "output":0}
})
},
uniq: {
type: Object,
default: Object.create({"total":0, "month":0, "year":0, "day":0})
}
},
data: () => ({
show: false,
margin_bt: 'margin-bottom: 0; margin-top: 0; '
}),
methods: {
showMe(b, srv) {
showMe(b) {
this.show = b;
this.uniq = srv['uniq'];
this.docker = srv['dockerStats'];
//this.uniq = srv['uniq'];
//this.docker = srv['dockerStats'];
},
bytesToHigh(bytes) {
if (bytes < 1024) return `${(bytes).toFixed(2)} Б`;

6
src/components/ActionDialogs/WorldwideMap.vue

@ -3,15 +3,15 @@
<md-dialog :md-active.sync="show" @close="show=false" style="z-index: 10">
<l-map style="height: 450px; width: 700px; border-radius: 3px; border: 3px solid #f4722b" :zoom="zoom" :center="center">
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<l-marker v-for="srv in this.$API.stats.servers['w']" :key="srv['name']" :lat-lng="srv['city_pos']">
<l-marker v-for="srv in Object.values(this.$API.stats.servers_map).filter(server => server['player_count']>0)" :key="srv['name']" :lat-lng="srv['city_pos']">
<l-icon class-name="icom-map">{{srv['name']}}</l-icon>
<l-popup><p class="p-map" v-on:click="$refs.wwm_ssd.openFIF(srv)">{{srv['name']}}<br>{{human_name_impl(srv['player_count'], srv['naming'])}}<br>Подключиться</p></l-popup>
</l-marker>
<l-marker v-for="srv in this.$API.stats.servers['e']" :key="srv['name']" :lat-lng="srv['city_pos']">
<l-marker v-for="srv in Object.values(this.$API.stats.servers_map).filter(server => server['player_count'] === 0 && server['status'] === true)" :key="srv['name']" :lat-lng="srv['city_pos']">
<l-icon class-name="icom-map"><div class="headline">{{srv['name']}}</div></l-icon>
<l-popup><p class="p-map" v-on:click="$refs.wwm_ssd.openFIF(srv)">{{srv['name']}}<br>{{human_name_impl(srv['player_count'], srv['naming'])}}<br>Подключиться</p></l-popup>
</l-marker>
<l-marker v-for="srv in this.$API.stats.servers['n']" :key="srv['name']" :lat-lng="srv['city_pos']">
<l-marker v-for="srv in Object.values(this.$API.stats.servers_map).filter(server => server['status'] === false)" :key="srv['name']" :lat-lng="srv['city_pos']">
<l-icon class-name="icom-map">{{srv['name']}}</l-icon>
<l-popup><p class="p-map">{{srv['name']}}<br>{{human_name_impl(srv['player_count'], srv['naming'])}}</p></l-popup>
</l-marker>

12
src/components/TabsMenuElements/ServersView/Components/ServerCard.vue

@ -3,14 +3,14 @@
<md-card>
<md-card-media-cover md-solid>
<md-card-media class="card-size" md-ratio="16:9">
<img :src="serverImage" :alt="serverName" crossorigin="anonymous" :style="imgIfStatus()">
<img :src="serverData['preview']" :alt="serverData['name']" crossorigin="anonymous" :style="imgIfStatus()">
</md-card-media>
<md-card-area class="md-card-area-server">
<md-card-header>
<span class="md-title sc-title" style="text-align: left; font-family: tf2build; font-size: 2.5em">{{serverName}}</span>
<span class="md-title sc-title" style="text-align: left; font-family: tf2build; font-size: 2.5em">{{serverData['name']}}</span>
<br class="sc-br">
<span class="md-subhead sc-subhead" style="text-align: left; font-family: tf2secondary; font-size: 3em">{{serverCurrentPlayer}}/{{serverMaxPlayer}}{{last_play===null?'':` | Играл: ${last_play}`}}</span>
<md-tooltip class="tooltip" md-direction="top">Нажми чтоб подключиться к {{serverName}}</md-tooltip>
<span class="md-subhead sc-subhead" style="text-align: left; font-family: tf2secondary; font-size: 3em">{{serverData['player_count']}}/{{serverData['max_players']}}{{last_play===null?'':` | Играл: ${last_play}`}}</span>
<md-tooltip class="tooltip" md-direction="top">Нажми чтоб подключиться к {{serverData['name']}}</md-tooltip>
</md-card-header>
</md-card-area>
</md-card-media-cover>
@ -26,10 +26,6 @@ export default {
name: 'ServerCard',
components: {ServerFullInfo},
props: {
serverImage: String,
serverName: String,
serverCurrentPlayer: Number,
serverMaxPlayer: Number,
serverData: {
type: Object,
default: null

28
src/components/TabsMenuElements/ServersView/Components/ServerFullInfo.vue

@ -4,7 +4,7 @@
<div class="md-layout md-alignment-bottom-center" style="z-index: 1">
<div class="md-layout-item md-size-5"/>
<div class="md-layout-item rounded-and-colored md-size-45 md-small-size-90">
<h3 class="txt-innert" style="text-align: center; margin: 2% 0%">{{serverInfo['name']}}</h3>
<h3 class="txt-innert" style="text-align: center; margin: 2% 0%">{{serverData['name']}}</h3>
</div>
<div class="md-layout-item rounded-and-colored-circle md-size-5 clickable" v-on:click="closeFIF()">
<h3 class="txt-innert" style="text-align: center; margin: 25% 0%">X</h3>
@ -12,20 +12,20 @@
</div>
<div class="md-layout md-alignment-bottom-center" style="margin-top: -2.5%">
<div class="md-layout-item md-size-50 server-info-rounded rounded-only md-small-size-100 md-scrollbar" style="height: 660px; overflow-y: auto;">
<img :src="serverInfo['preview']" style="width: 100%; height:12em;object-fit: cover;border-top-left-radius: 15px; border-top-right-radius: 15px">
<img :src="serverData['preview']" style="width: 100%; height:12em;object-fit: cover;border-top-left-radius: 15px; border-top-right-radius: 15px">
<div>
<p class="p-server">{{serverInfo['description']}}</p>
<p class="p-server">{{serverData['description']}}</p>
<div v-if="this.$API.player.auth('steam') === true" style="text-align: center; font-size: 0.5em !important;">
<p class="p-server clickable" style="display: inline" v-on:click="$refs.sfi_md.showMe(true, undefined, serverInfo['key'])">Чат сервера</p>
<p class="p-server clickable" style="display: inline" v-on:click="$refs.sfi_md.showMe(true, undefined, serverData['key'])">Чат сервера</p>
<p class="p-server" style="display: inline"> | </p>
<p class="p-server clickable" style="display: inline" v-on:click="$refs.sfi_kdt.showMe(true, 1, serverInfo['key'])">Топ убийств</p>
<p class="p-server clickable" style="display: inline" v-on:click="$refs.sfi_kdt.showMe(true, 1, serverData['key'])">Топ убийств</p>
<p class="p-server" style="display: inline"> | </p>
<p class="p-server clickable" style="display: inline" v-on:click="$refs.sfi_kdt.showMe(true, 2, serverInfo['key'])">Топ смертей</p>
<p class="p-server clickable" style="display: inline" v-on:click="$refs.sfi_kdt.showMe(true, 2, serverData['key'])">Топ смертей</p>
<p class="p-server" style="display: inline"> | </p>
<p class="p-server clickable" style="display: inline" v-on:click="$refs.sfi_ssd.showMe(true, serverInfo)">Статистика</p>
<p class="p-server clickable" style="display: inline" v-on:click="$refs.sfi_ssd.showMe(true, serverData)">Статистика</p>
</div>
<div v-else style="text-align: center; font-size: 0.5em !important;">
<p class="p-server clickable" style="display: inline" v-on:click="$refs.sfi_ssd.showMe(true, serverInfo)">Статистика сервера</p>
<p class="p-server clickable" style="display: inline" v-on:click="$refs.sfi_ssd.showMe(true, serverData)">Статистика сервера</p>
</div>
<hr width="30%">
</div>
@ -33,9 +33,9 @@
<div style="max-width: 40%; float: left;" v-on:click="onMove('steam')" class="clickable">
<TerminalSvg class="img-server"/>
<p class="p-server" style="margin-bottom: -5%">Подключиться</p>
<p class="p-server-address">{{serverInfo['address']}}</p>
<p class="p-server-address">{{serverData['address']}}</p>
</div>
<div style="max-width: 40%; float: left;" v-if="serverInfo['workshop'].length > 0" v-on:click="onMove('workshop')" class="clickable">
<div style="max-width: 40%; float: left;" v-if="serverData['workshop'].length > 0" v-on:click="onMove('workshop')" class="clickable">
<SteamSvg class="img-server"/>
<p class="p-server" style="margin-bottom: -5%">Workshop</p>
<p class="p-server-address">by Пельмень</p>
@ -47,9 +47,9 @@
</div>
</div>
<hr width="30%">
<h3 v-if="serverInfo['player_count'] < 1" style="text-align: center; line-height: 1em">На сервере пусто, заходи с друзьями...</h3>
<h3 v-if="serverData['player_count'] < 1" style="text-align: center; line-height: 1em">На сервере пусто, заходи с друзьями...</h3>
<div v-else>
<h3 style="text-align: center" class="sfi-current-player">Сейчас играет {{serverInfo['player_count']}}/{{serverInfo['max_players']}}</h3>
<h3 style="text-align: center" class="sfi-current-player">Сейчас играет {{serverData['player_count']}}/{{serverData['max_players']}}</h3>
<hr width="30%">
<md-table v-model="players" md-sort="score" md-sort-order="desc" md-card md-fixed-header @md-selected="openPlayer" md-height="150px">
<md-table-row slot="md-table-row" slot-scope="{ item }" md-selectable="single">
@ -61,13 +61,13 @@
</md-table>
<PlayerExtendedInfo ref="pei" :player="selected_player"/>
</div>
<p class="p-server" style="text-align: center; margin: 2.5% 0;">Обновлен: {{(new Date(serverInfo['last_update']*1000)).toLocaleString()}}</p>
<p class="p-server" style="text-align: center; margin: 2.5% 0;">Обновлен: {{(new Date(serverData['last_update']*1000)).toLocaleString()}}</p>
</div>
</div>
</md-dialog>
<MessagesDialog ref="sfi_md"/>
<KillDeadTop ref="sfi_kdt"/>
<ServerStatsDialog ref="sfi_ssd"/>
<ServerStatsDialog ref="sfi_ssd" :docker="serverData.dockerStats" :uniq="serverData.uniq"/>
</div>
</template>

43
src/components/TabsMenuElements/ServersView/ServersView.vue

@ -3,11 +3,9 @@
<div class="md-layout md-alignment-bottom-center md-small-hide" style="margin-bottom: -1%; margin-top: 1%">
<CharacterImage :size="10" :img_src="require(`@/assets/images/characters/toilet.png`)" :audio_src="require(`@/assets/sounds/puk.mp3`)"/>
</div>
<div class="md-layout md-alignment-bottom-center" v-on:click="updateServers()">
<div class="md-layout-item md-size-25 md-small-size-100 md-alignment-bottom-center rounded-and-colored clickable" style="z-index: 1">
<h3 class="txt-innert" style="text-align: center; margin: 4% 0%; line-height: 1em">Список серверов
<md-tooltip class="tooltip" md-direction="top">Нажми чтоб обновить его</md-tooltip>
</h3>
<div class="md-layout md-alignment-bottom-center">
<div class="md-layout-item md-size-25 md-small-size-100 md-alignment-bottom-center rounded-and-colored" style="z-index: 1">
<h3 class="txt-innert" style="text-align: center; margin: 4% 0%; line-height: 1em">Список серверов</h3>
</div>
</div>
<div class="md-layout md-alignment-bottom-center" style="margin-top: -1.5%">
@ -27,12 +25,28 @@
<h5 style="margin: 0% 0%; display: inline" class="clickable" v-on:click="$refs.sv_ssd.showMe(true)">Статистика</h5>
</div>
<hr>
<h5 style="text-align: center" v-if="this.$API.stats.servers['w'].length>0">где сейчас играют карлики</h5>
<ServerCard v-for="srv in this.$API.stats.servers['w']" :key="srv['name']" :server-name="srv['name']" :server-image="srv['preview']" :server-current-player="srv['player_count']" :server-max-player="srv['max_players']" :server-data="srv" :last_play="getLastPlay(srv['key'])"/>
<h5 style="text-align: center" v-if="this.$API.stats.servers['e'].length>0">где сейчас никого нет</h5>
<ServerCard v-for="srv in this.$API.stats.servers['e']" :key="srv['name']" :server-name="srv['name']" :server-image="srv['preview']" :server-current-player="srv['player_count']" :server-max-player="srv['max_players']" :server-data="srv" :last_play="getLastPlay(srv['key'])"/>
<h5 style="text-align: center" v-if="this.$API.stats.servers['n'].length>0">где сейчас играют карлики</h5>
<ServerCard v-for="srv in this.$API.stats.servers['n']" :key="srv['name']" :server-name="srv['name']" :server-image="srv['preview']" :server-current-player="srv['player_count']" :server-max-player="srv['max_players']" :server-data="srv" :last_play="getLastPlay(srv['key'])"/>
<!---->
<h5 style="text-align: center" v-if="Object.values(this.$API.stats.servers_map).filter(server => server['player_count']>0).length>0">где сейчас играют карлики</h5>
<ServerCard
v-for="srv in Object.values(this.$API.stats.servers_map).filter(server => server['player_count']>0).sort((s1, s2) => s2.player_count - s1.player_count)"
:key="srv['name']"
:server-data="srv"
:last_play="getLastPlay(srv['key'])"/>
<!---->
<h5 style="text-align: center" v-if="Object.values(this.$API.stats.servers_map).filter(server => server['player_count'] === 0 && server['status'] === true).length>0">где сейчас никого нет</h5>
<ServerCard
v-for="srv in Object.values(this.$API.stats.servers_map).filter(server => server['player_count'] === 0 && server['status'] === true)"
:key="srv['name']"
:server-data="srv"
:last_play="getLastPlay(srv['key'])"/>
<!---->
<h5 style="text-align: center" v-if="Object.values(this.$API.stats.servers_map).filter(server => server['status'] === false).length>0">где сейчас играют карлики</h5>
<ServerCard
v-for="srv in Object.values(this.$API.stats.servers_map).filter(server => server['status'] === false)"
:key="srv['name']"
:server-data="srv"
:last_play="getLastPlay(srv['key'])"/>
</div>
</div>
<SnackLoader ref="s_loader" s_text="Обновление списка серверов"/>
@ -59,13 +73,6 @@ export default {
lp_cache: null
}),
methods: {
updateServers() {
this.$refs.s_loader.setLoading(true);
this.$API.fillServers().then(() => {
this.servers = this.$API.stats.servers;
this.$refs.s_loader.setLoading(false);
})
},
getLastPlay(srv) {
if (this.$API.player.store !== null) {
if (this.lp_cache == null) this.lp_cache = this.$API.player.getLastplayList(this.$API.player.store);

Loading…
Cancel
Save