Plan/Plan/common/src/main/java/com/djrapitops/plan/placeholder/PlayerPlaceHolders.java

456 lines
19 KiB
Java

/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.placeholder;
import com.djrapitops.plan.delivery.domain.container.PlayerContainer;
import com.djrapitops.plan.delivery.domain.keys.PlayerKeys;
import com.djrapitops.plan.delivery.domain.mutators.*;
import com.djrapitops.plan.delivery.formatting.Formatter;
import com.djrapitops.plan.delivery.formatting.Formatters;
import com.djrapitops.plan.gathering.afk.AFKTracker;
import com.djrapitops.plan.gathering.cache.SessionCache;
import com.djrapitops.plan.gathering.domain.ActiveSession;
import com.djrapitops.plan.gathering.domain.FinishedSession;
import com.djrapitops.plan.gathering.domain.GeoInfo;
import com.djrapitops.plan.gathering.domain.PlayerKill;
import com.djrapitops.plan.gathering.domain.event.JoinAddress;
import com.djrapitops.plan.identification.Server;
import com.djrapitops.plan.identification.ServerInfo;
import com.djrapitops.plan.settings.config.PlanConfig;
import com.djrapitops.plan.settings.config.paths.TimeSettings;
import com.djrapitops.plan.settings.locale.Locale;
import com.djrapitops.plan.settings.locale.lang.GenericLang;
import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
import com.djrapitops.plan.utilities.Predicates;
import org.jetbrains.annotations.NotNull;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Optional;
import static com.djrapitops.plan.utilities.MiscUtils.*;
/**
* Placeholders about a player.
*
* @author aidn5, AuroraLS3
*/
@Singleton
public class PlayerPlaceHolders implements Placeholders {
private final Locale locale;
private final PlanConfig config;
private final DBSystem dbSystem;
private final ServerInfo serverInfo;
private final Formatters formatters;
@Inject
public PlayerPlaceHolders(
Locale locale,
PlanConfig config,
DBSystem dbSystem,
ServerInfo serverInfo,
Formatters formatters
) {
this.locale = locale;
this.config = config;
this.dbSystem = dbSystem;
this.serverInfo = serverInfo;
this.formatters = formatters;
}
@Override
public void register(
PlanPlaceholders placeholders
) {
Formatter<Double> decimals = formatters.decimals();
Formatter<Long> year = formatters.yearLong();
Formatter<Long> time = formatters.timeAmount();
placeholders.register("player_is_afk", this::isAfk);
placeholders.register("player_is_afk_badge", player -> isAfk(player) ? "AFK" : "");
placeholders.register("player_banned",
player -> player.getValue(PlayerKeys.BANNED)
.orElse(Boolean.FALSE)
);
placeholders.register("player_operator",
player -> player.getValue(PlayerKeys.OPERATOR)
.orElse(Boolean.FALSE)
);
placeholders.register("player_sessions_count",
player -> SessionsMutator.forContainer(player)
.count()
);
placeholders.register("player_kick_count",
player -> player.getValue(PlayerKeys.KICK_COUNT)
.orElse(0)
);
placeholders.register("player_death_count",
player -> player.getValue(PlayerKeys.DEATH_COUNT)
.orElse(0)
);
placeholders.register("player_mob_kill_count",
player -> player.getValue(PlayerKeys.MOB_KILL_COUNT)
.orElse(0)
);
placeholders.register("player_player_kill_count",
player -> player.getValue(PlayerKeys.PLAYER_KILL_COUNT)
.orElse(0)
);
placeholders.register("player_kill_death_ratio",
player -> PlayerVersusMutator.forContainer(player).toKillDeathRatio());
placeholders.register("player_ping_average_day",
player -> decimals.apply(PingMutator.forContainer(player)
.filterBy(Predicates.within(dayAgo(), now()))
.average()) + " ms"
);
placeholders.register("player_ping_average_week",
player -> decimals.apply(PingMutator.forContainer(player)
.filterBy(Predicates.within(weekAgo(), now()))
.average()) + " ms"
);
placeholders.register("player_ping_average_month",
player -> decimals.apply(PingMutator.forContainer(player)
.filterBy(Predicates.within(monthAgo(), now()))
.average()) + " ms"
);
placeholders.register("player_lastseen",
player -> year.apply(player.getValue(PlayerKeys.LAST_SEEN)
.orElse((long) 0))
);
placeholders.register("player_registered",
player -> year.apply(player.getValue(PlayerKeys.REGISTERED)
.orElse((long) 0))
);
placeholders.register("player_geolocation",
player -> GeoInfoMutator.forContainer(player)
.mostRecent()
.map(GeoInfo::getGeolocation)
.orElse(locale.getString(GenericLang.UNKNOWN))
);
placeholders.register("player_join_address",
player -> SessionsMutator.forContainer(player)
.latestSession()
.flatMap(session -> session.getExtraData(JoinAddress.class))
.map(JoinAddress::getAddress)
.orElse(locale.getString(GenericLang.UNKNOWN))
);
registerPlaytimePlaceholders(placeholders, time);
registerSessionLengethPlaceholders(placeholders, time);
placeholders.register("player_favorite_server",
player -> PerServerMutator.forContainer(player).favoriteServer()
.flatMap(serverUUID -> dbSystem.getDatabase().query(ServerQueries.fetchServerMatchingIdentifier(serverUUID)))
.map(Server::getName)
.orElse("-")
);
placeholders.register("player_activity_index",
player -> decimals.apply(player.getActivityIndex(
now(),
config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD)
).getValue())
);
placeholders.register("player_activity_group",
player -> player.getActivityIndex(
now(),
config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD)
).getGroup()
);
registerKillPlaceholders(placeholders);
}
private void registerSessionLengethPlaceholders(PlanPlaceholders placeholders, Formatter<Long> time) {
placeholders.register("player_current_session_length",
player -> time.apply(getActiveSessionLength(player).orElse(-1L)));
placeholders.register("player_current_session_length_raw",
player -> getActiveSessionLength(player).orElse(0L));
placeholders.register("player_latest_session_length",
player -> time.apply(getActiveSessionLength(player)
.orElseGet(() -> SessionsMutator.forContainer(player).latestSession()
.map(FinishedSession::getLength)
.orElse(-1L))));
placeholders.register("player_latest_session_length_raw",
player -> getActiveSessionLength(player)
.orElseGet(() -> SessionsMutator.forContainer(player).latestSession()
.map(FinishedSession::getLength)
.orElse(0L)));
placeholders.register("player_previous_session_length",
player -> time.apply(SessionsMutator.forContainer(player).previousSession()
.map(FinishedSession::getLength)
.orElse(-1L)));
placeholders.register("player_previous_session_length_raw",
player -> SessionsMutator.forContainer(player).previousSession()
.map(FinishedSession::getLength)
.orElse(0L));
}
private boolean isAfk(PlayerContainer player) {
return SessionCache.getCachedSession(player.getUnsafe(PlayerKeys.UUID))
.map(ActiveSession::getLastMovementForAfkCalculation)
.filter(lastMovement -> lastMovement != AFKTracker.IGNORES_AFK
&& now() - lastMovement > config.get(TimeSettings.AFK_THRESHOLD))
.isPresent();
}
private void registerKillPlaceholders(PlanPlaceholders placeholders) {
Formatter<Double> decimals = formatters.decimals();
placeholders.register("player_player_caused_deaths",
player -> PlayerVersusMutator.forContainer(player).toPlayerDeathCount()
);
placeholders.register("player_deaths",
player -> PlayerVersusMutator.forContainer(player).toDeathCount()
);
placeholders.register("player_mob_caused_deaths",
player -> PlayerVersusMutator.forContainer(player).toMobDeathCount()
);
placeholders.register("player_kdr",
player -> decimals.apply(PlayerVersusMutator.forContainer(player).toKillDeathRatio())
);
placeholders.register("player_mob_kdr",
player -> decimals.apply(PlayerVersusMutator.forContainer(player).toMobKillDeathRatio())
);
for (int i = 1; i <= 10; i++) {
final int index = i;
placeholders.register("player_recent_kill_" + index,
player -> player.getValue(PlayerKeys.PLAYER_KILLS)
.filter(list -> list.size() >= index)
.map(list -> list.get(index - 1))
.map(PlayerKill::getVictim)
.map(PlayerKill.Victim::getName)
.orElse("-")
);
placeholders.register("player_recent_death_" + index,
player -> player.getValue(PlayerKeys.PLAYER_DEATHS_KILLS)
.filter(list -> list.size() >= index)
.map(list -> list.get(index - 1))
.map(PlayerKill::getKiller)
.map(PlayerKill.Killer::getName)
.orElse("-")
);
}
}
private void registerPlaytimePlaceholders(PlanPlaceholders placeholders, Formatter<Long> time) {
registerActivePlaytimePlaceholders(placeholders, time);
registerAfkTimePlaceholders(placeholders, time);
registerPlayerPlaytimePlaceholders(placeholders, time);
registerServerSpecificPlaytimePlaceholders(placeholders, time);
}
private void registerServerSpecificPlaytimePlaceholders(PlanPlaceholders placeholders, Formatter<Long> time) {
placeholders.register("player_server_time_active",
player -> time.apply(SessionsMutator.forContainer(player)
.filterPlayedOnServer(serverInfo.getServerUUID())
.toActivePlaytime())
);
placeholders.register("player_server_time_active_raw",
player -> SessionsMutator.forContainer(player)
.filterPlayedOnServer(serverInfo.getServerUUID())
.toActivePlaytime()
);
placeholders.register("player_server_time_afk",
player -> time.apply(SessionsMutator.forContainer(player)
.filterPlayedOnServer(serverInfo.getServerUUID())
.toAfkTime())
);
placeholders.register("player_server_time_afk_raw",
player -> SessionsMutator.forContainer(player)
.filterPlayedOnServer(serverInfo.getServerUUID())
.toAfkTime()
);
placeholders.register("player_server_time_total",
player -> time.apply(SessionsMutator.forContainer(player)
.filterPlayedOnServer(serverInfo.getServerUUID())
.toPlaytime())
);
placeholders.register("player_server_time_total_raw",
player -> SessionsMutator.forContainer(player)
.filterPlayedOnServer(serverInfo.getServerUUID())
.toPlaytime()
);
placeholders.register("player_server_time_day",
player -> time.apply(SessionsMutator.forContainer(player)
.filterSessionsBetween(dayAgo(), now())
.filterPlayedOnServer(serverInfo.getServerUUID())
.toPlaytime())
);
placeholders.register("player_server_time_day_raw",
player -> SessionsMutator.forContainer(player)
.filterSessionsBetween(dayAgo(), now())
.filterPlayedOnServer(serverInfo.getServerUUID())
.toPlaytime()
);
placeholders.register("player_server_time_week",
player -> time.apply(SessionsMutator.forContainer(player)
.filterSessionsBetween(weekAgo(), now())
.filterPlayedOnServer(serverInfo.getServerUUID())
.toPlaytime())
);
placeholders.register("player_server_time_week_raw",
player -> SessionsMutator.forContainer(player)
.filterSessionsBetween(weekAgo(), now())
.filterPlayedOnServer(serverInfo.getServerUUID())
.toPlaytime()
);
placeholders.register("player_server_time_month",
player -> time.apply(SessionsMutator.forContainer(player)
.filterSessionsBetween(monthAgo(), now())
.filterPlayedOnServer(serverInfo.getServerUUID())
.toPlaytime())
);
placeholders.register("player_server_time_month_raw",
player -> SessionsMutator.forContainer(player)
.filterSessionsBetween(monthAgo(), now())
.filterPlayedOnServer(serverInfo.getServerUUID())
.toPlaytime()
);
}
private void registerPlayerPlaytimePlaceholders(PlanPlaceholders placeholders, Formatter<Long> time) {
placeholders.register("player_time_total",
player -> time.apply(SessionsMutator.forContainer(player)
.toPlaytime())
);
placeholders.register("player_time_total_raw",
player -> SessionsMutator.forContainer(player)
.toPlaytime()
);
placeholders.register("player_time_day",
player -> time.apply(SessionsMutator.forContainer(player)
.filterSessionsBetween(dayAgo(), now())
.toPlaytime())
);
placeholders.register("player_time_day_raw",
player -> SessionsMutator.forContainer(player)
.filterSessionsBetween(dayAgo(), now())
.toPlaytime()
);
placeholders.register("player_time_week",
player -> time.apply(SessionsMutator.forContainer(player)
.filterSessionsBetween(weekAgo(), now())
.toPlaytime())
);
placeholders.register("player_time_week_raw",
player -> SessionsMutator.forContainer(player)
.filterSessionsBetween(weekAgo(), now())
.toPlaytime()
);
placeholders.register("player_time_month",
player -> time.apply(SessionsMutator.forContainer(player)
.filterSessionsBetween(monthAgo(), now())
.toPlaytime())
);
placeholders.register("player_time_month_raw",
player -> SessionsMutator.forContainer(player)
.filterSessionsBetween(monthAgo(), now())
.toPlaytime()
);
}
private void registerAfkTimePlaceholders(PlanPlaceholders placeholders, Formatter<Long> time) {
placeholders.register("player_time_afk",
player -> time.apply(SessionsMutator.forContainer(player)
.toAfkTime())
);
placeholders.register("player_time_afk_raw",
player -> SessionsMutator.forContainer(player)
.toAfkTime()
);
}
private void registerActivePlaytimePlaceholders(PlanPlaceholders placeholders, Formatter<Long> time) {
placeholders.register("player_time_active",
player -> time.apply(SessionsMutator.forContainer(player)
.toActivePlaytime())
);
placeholders.register("player_time_active_raw",
player -> SessionsMutator.forContainer(player)
.toActivePlaytime()
);
placeholders.register("player_time_active_day",
player -> time.apply(SessionsMutator.forContainer(player)
.filterSessionsBetween(dayAgo(), now())
.toActivePlaytime())
);
placeholders.register("player_time_active_day_raw",
player -> SessionsMutator.forContainer(player)
.filterSessionsBetween(dayAgo(), now())
.toActivePlaytime()
);
placeholders.register("player_time_active_week",
player -> time.apply(SessionsMutator.forContainer(player)
.filterSessionsBetween(weekAgo(), now())
.toActivePlaytime())
);
placeholders.register("player_time_active_week_raw",
player -> SessionsMutator.forContainer(player)
.filterSessionsBetween(weekAgo(), now())
.toActivePlaytime()
);
placeholders.register("player_time_active_month",
player -> time.apply(SessionsMutator.forContainer(player)
.filterSessionsBetween(monthAgo(), now())
.toActivePlaytime())
);
placeholders.register("player_time_active_month_raw",
player -> SessionsMutator.forContainer(player)
.filterSessionsBetween(monthAgo(), now())
.toActivePlaytime()
);
}
@NotNull
private Optional<Long> getActiveSessionLength(PlayerContainer player) {
SessionCache.refreshActiveSessionsState();
return SessionCache.getCachedSession(player.getUnsafe(PlayerKeys.UUID))
.map(ActiveSession::toFinishedSessionFromStillActive)
.map(FinishedSession::getLength);
}
}