Plan/Plan/common/src/main/java/com/djrapitops/plan/gathering/events/PlayerJoinEventConsumer.java

217 lines
9.5 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.gathering.events;
import com.djrapitops.plan.delivery.domain.Nickname;
import com.djrapitops.plan.delivery.domain.PlayerName;
import com.djrapitops.plan.delivery.domain.ServerName;
import com.djrapitops.plan.delivery.export.Exporter;
import com.djrapitops.plan.extension.CallEvents;
import com.djrapitops.plan.extension.ExtensionSvc;
import com.djrapitops.plan.gathering.JoinAddressValidator;
import com.djrapitops.plan.gathering.cache.NicknameCache;
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.event.JoinAddress;
import com.djrapitops.plan.gathering.domain.event.PlayerJoin;
import com.djrapitops.plan.gathering.geolocation.GeolocationCache;
import com.djrapitops.plan.identification.ServerUUID;
import com.djrapitops.plan.processing.Processing;
import com.djrapitops.plan.settings.config.PlanConfig;
import com.djrapitops.plan.settings.config.paths.DataGatheringSettings;
import com.djrapitops.plan.settings.config.paths.ExportSettings;
import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.sql.tables.JoinAddressTable;
import com.djrapitops.plan.storage.database.transactions.Transaction;
import com.djrapitops.plan.storage.database.transactions.events.*;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
@Singleton
public class PlayerJoinEventConsumer {
private final Processing processing;
private final PlanConfig config;
private final DBSystem dbSystem;
private final JoinAddressValidator joinAddressValidator;
private final GeolocationCache geolocationCache;
private final SessionCache sessionCache;
private final NicknameCache nicknameCache;
private final ExtensionSvc extensionService;
private final Exporter exporter;
@Inject
public PlayerJoinEventConsumer(
Processing processing,
PlanConfig config,
DBSystem dbSystem, JoinAddressValidator joinAddressValidator,
GeolocationCache geolocationCache,
SessionCache sessionCache,
NicknameCache nicknameCache,
ExtensionSvc extensionService,
Exporter exporter
) {
this.processing = processing;
this.config = config;
this.dbSystem = dbSystem;
this.joinAddressValidator = joinAddressValidator;
this.geolocationCache = geolocationCache;
this.sessionCache = sessionCache;
this.nicknameCache = nicknameCache;
this.extensionService = extensionService;
this.exporter = exporter;
}
public void onJoinGameServer(PlayerJoin join) {
Optional<FinishedSession> interruptedSession = cacheActiveSession(join);
processing.submitCritical(() -> {
storeWorldInformation(join);
storeGamePlayer(join)
.thenRunAsync(() -> {
storeJoinAddress(join);
interruptedSession.ifPresent(this::storeInterruptedSession);
storeGeolocation(join);
storeOperatorStatus(join);
storeNickname(join);
updatePlayerDataExtensionValues(join);
updateExport(join);
}, processing.getCriticalExecutor());
});
}
public void onJoinProxyServer(PlayerJoin join) {
cacheActiveSession(join);
processing.submitCritical(() -> storeProxyPlayer(join)
.thenRunAsync(() -> {
storeGeolocation(join);
updatePlayerDataExtensionValues(join);
updateExport(join);
}, processing.getCriticalExecutor())
);
}
private void storeJoinAddress(PlayerJoin join) {
join.getPlayer().getJoinAddress()
.map(joinAddressValidator::sanitize)
.filter(joinAddressValidator::isValid)
.map(StoreJoinAddressTransaction::new)
.ifPresent(dbSystem.getDatabase()::executeTransaction);
}
private void storeGeolocation(PlayerJoin join) {
if (config.isTrue(DataGatheringSettings.GEOLOCATIONS) && geolocationCache.canGeolocate()) {
join.getPlayer().getIPAddress()
.map(ip -> new StoreGeoInfoTransaction(join.getPlayerUUID(), ip, join.getTime(), geolocationCache::getCountry))
.ifPresent(dbSystem.getDatabase()::executeTransaction);
}
}
private void storeWorldInformation(PlayerJoin join) {
ServerUUID serverUUID = join.getServerUUID();
join.getPlayer().getCurrentWorld()
.map(world -> new StoreWorldNameTransaction(serverUUID, world))
.ifPresent(dbSystem.getDatabase()::executeTransaction);
}
private static long getRegisterDate(PlayerJoin join) {
long registerDate = join.getPlayer().getRegisterDate().orElseGet(join::getTime);
// Correct incorrect register dates https://github.com/plan-player-analytics/Plan/issues/2934
if (registerDate < System.currentTimeMillis() / 1000) {
registerDate = registerDate * 1000;
}
return registerDate;
}
private CompletableFuture<?> storeGamePlayer(PlayerJoin join) {
long registerDate = getRegisterDate(join);
String joinAddress = join.getPlayer().getJoinAddress()
.map(joinAddressValidator::sanitize)
.filter(joinAddressValidator::isValid)
.orElse(JoinAddressTable.DEFAULT_VALUE_FOR_LOOKUP);
Transaction transaction = new StoreServerPlayerTransaction(
join.getPlayerUUID(), registerDate, join.getPlayer().getName(), join.getServerUUID(), joinAddress
);
return dbSystem.getDatabase().executeTransaction(transaction);
}
private CompletableFuture<?> storeProxyPlayer(PlayerJoin join) {
Transaction transaction = new PlayerRegisterTransaction(
join.getPlayerUUID(), join::getTime, join.getPlayer().getName()
);
return dbSystem.getDatabase().executeTransaction(transaction);
}
private void storeOperatorStatus(PlayerJoin join) {
join.getPlayer().isOperator()
.map(opStatus -> new OperatorStatusTransaction(join.getPlayerUUID(), join.getServerUUID(), opStatus))
.ifPresent(dbSystem.getDatabase()::executeTransaction);
}
Optional<FinishedSession> cacheActiveSession(PlayerJoin join) {
ActiveSession session = mapToActiveSession(join);
return sessionCache.cacheSession(join.getPlayerUUID(), session);
}
private void storeInterruptedSession(FinishedSession finishedSession) {
dbSystem.getDatabase().executeTransaction(new StoreSessionTransaction(finishedSession));
}
private ActiveSession mapToActiveSession(PlayerJoin join) {
String joinAddress = join.getPlayer().getJoinAddress()
.map(joinAddressValidator::sanitize)
.filter(joinAddressValidator::isValid)
.orElse(JoinAddressTable.DEFAULT_VALUE_FOR_LOOKUP);
ActiveSession session = new ActiveSession(join.getPlayerUUID(), join.getServerUUID(), join.getTime(),
join.getPlayer().getCurrentWorld().orElse(null),
join.getPlayer().getCurrentGameMode().orElse(null));
session.getExtraData().put(PlayerName.class, new PlayerName(join.getPlayer().getName()));
session.getExtraData().put(ServerName.class, new ServerName(join.getServer().isProxy() ? join.getServer().getName() : "Proxy Server"));
session.getExtraData().put(JoinAddress.class, new JoinAddress(joinAddress));
return session;
}
private void storeNickname(PlayerJoin join) {
join.getPlayer().getDisplayName()
.map(displayName -> new Nickname(displayName, join.getTime(), join.getServerUUID()))
.map(nickname -> new StoreNicknameTransaction(
join.getPlayerUUID(), nickname,
(uuid, name) -> nicknameCache.getDisplayName(join.getPlayerUUID())
.map(name::equals)
.orElse(false)))
.ifPresent(dbSystem.getDatabase()::executeTransaction);
}
private void updatePlayerDataExtensionValues(PlayerJoin join) {
processing.submitNonCritical(() -> extensionService.updatePlayerValues(
join.getPlayerUUID(), join.getPlayerName(), CallEvents.PLAYER_JOIN)
);
}
void updateExport(PlayerJoin join) {
if (config.isTrue(ExportSettings.EXPORT_ON_ONLINE_STATUS_CHANGE)) {
processing.submitNonCritical(() -> exporter.exportPlayerPage(join.getPlayerUUID(), join.getPlayerName()));
}
}
}