Added some data pipelines, not in use yet

This commit is contained in:
Risto Lahtela 2021-11-21 20:10:27 +02:00
parent e0a4779ab6
commit 6c0da9e167
14 changed files with 651 additions and 44 deletions

View File

@ -0,0 +1,93 @@
/*
* 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.modules.bukkit;
import com.djrapitops.plan.DataService;
import com.djrapitops.plan.exceptions.MissingPipelineException;
import com.djrapitops.plan.gathering.cache.JoinAddressCache;
import com.djrapitops.plan.gathering.domain.PlayerMetadata;
import com.djrapitops.plan.gathering.domain.event.JoinAddress;
import com.djrapitops.plan.gathering.domain.event.PlayerJoin;
import com.djrapitops.plan.gathering.domain.event.PlayerLeave;
import com.djrapitops.plan.identification.ServerUUID;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoSet;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import javax.inject.Singleton;
import java.net.InetSocketAddress;
import java.util.Optional;
import java.util.UUID;
@Module
public class BukkitEventPipelineModule {
@Provides
@Singleton
@IntoSet
DataService.Pipeline metadata(JoinAddressCache joinAddressCache) {
return service -> service
.registerMapper(UUID.class, Player.class, PlayerMetadata.class,
player -> getPlayerMetadata(player, service, joinAddressCache));
}
private PlayerMetadata getPlayerMetadata(Player player, DataService service, JoinAddressCache joinAddressCache) {
return PlayerMetadata.builder()
.playerName(player.getName())
.displayName(player.getDisplayName())
.world(player.getWorld().getName())
.gameMode(Optional.ofNullable(player.getGameMode()).map(GameMode::name).orElse(null))
.ipAddress(Optional.ofNullable(player.getAddress()).map(InetSocketAddress::getAddress).orElse(null))
.joinAddress(service.pullWithoutId(JoinAddress.class).map(JoinAddress::getAddress).orElse(null))
.build();
}
@Provides
@Singleton
@IntoSet
DataService.Pipeline events() {
return service -> service
.registerDataServiceMapper(UUID.class, PlayerJoinEvent.class, PlayerJoin.class, this::mapToPlayerJoin)
.registerDataServiceMapper(UUID.class, PlayerQuitEvent.class, PlayerLeave.class, this::mapToPlayerLeave);
}
private PlayerJoin mapToPlayerJoin(DataService service, PlayerJoinEvent event) {
UUID playerUUID = event.getPlayer().getUniqueId();
Optional<PlayerMetadata> metadata = service.map(playerUUID, event.getPlayer(), PlayerMetadata.class);
return PlayerJoin.builder()
.playerUUID(playerUUID)
.serverUUID(service.pullWithoutId(ServerUUID.class).orElseThrow(MissingPipelineException::new))
.playerMetadata(metadata.orElseThrow(MissingPipelineException::new))
.time(System.currentTimeMillis())
.build();
}
private PlayerLeave mapToPlayerLeave(DataService service, PlayerQuitEvent event) {
UUID playerUUID = event.getPlayer().getUniqueId();
Optional<PlayerMetadata> metadata = service.map(playerUUID, event.getPlayer(), PlayerMetadata.class);
return PlayerLeave.builder()
.playerUUID(playerUUID)
.serverUUID(service.pullWithoutId(ServerUUID.class).orElseThrow(MissingPipelineException::new))
.playerMetadata(metadata.orElseThrow(MissingPipelineException::new))
.time(System.currentTimeMillis())
.build();
}
}

View File

@ -34,11 +34,19 @@ public interface DataService {
<K, T> void push(K identifier, T value, Class<T> type);
default <K, A, B> DataService registerOptionalMapper(Class<K> identifierType, Class<A> from, Class<B> to, BiFunction<K, A, Optional<B>> mapper) {
return registerMapper(identifierType, from, to, (id, value) -> mapper.apply(id, value).orElse(null));
}
<K, A, B> DataService registerMapper(Class<K> identifierType, Class<A> from, Class<B> to, BiFunction<K, A, B> mapper);
<K, A, B> DataService registerMapper(Class<K> identifierType, Class<A> from, Class<B> to, Function<A, B> mapper);
<K1, K2, A, B> DataService registerMapper(Class<K1> fromIdentifier, Class<A> from, Class<K2> toIdentifier, Class<B> to, TriConsumer<K1, A, BiConsumer<K2, B>> mapper);
default <K, A, B> DataService registerDataServiceMapper(Class<K> identifierType, Class<A> from, Class<B> to, BiFunction<DataService, A, B> mapper) {
return registerMapper(identifierType, from, to, value -> mapper.apply(this, value));
}
<K, Y, A, B> DataService registerMapper(Class<K> fromIdentifier, Class<A> from, Class<Y> toIdentifier, Class<B> to, TriConsumer<K, A, BiConsumer<Y, B>> mapper);
<K, T> DataService registerSink(Class<K> identifierType, Class<T> type, BiConsumer<K, T> consumer);
@ -46,16 +54,22 @@ public interface DataService {
<K, T> Optional<T> pull(Class<T> type, K identifier);
<T> Optional<T> pull(Class<T> type);
<T> Optional<T> pullWithoutId(Class<T> type);
<K, T> DataService registerPullSource(Class<K> identifierType, Class<T> type, Function<K, T> source);
default <K, T> DataService registerOptionalPullSource(Class<K> identifierType, Class<T> type, Function<K, Optional<T>> source) {
return registerPullSource(identifierType, type, id -> source.apply(id).orElse(null));
}
<K, T> DataService registerDatabasePullSource(Class<K> identifierType, Class<T> type, Function<K, Query<T>> source);
<T> DataService registerPullSource(Class<T> type, Supplier<T> source);
<T> DataService registerDatabasePullSource(Class<T> type, Supplier<Query<T>> source);
<K, A, B> Optional<B> map(K identifier, A value, Class<B> toType);
interface Pipeline {
void register(DataService service);
}

View File

@ -62,11 +62,22 @@ public class DataSvc implements DataService {
}
for (Mapper mapper : mappers.get(classPair)) {
Class convertingTo = mapper.typeB;
push(identifier, mapper.func.apply(identifier, value), convertingTo);
push(identifier, mapper.func.apply(identifier, value), mapper.typeB);
}
}
@Override
public <K, A, B> Optional<B> map(K identifier, A value, Class<B> toType) {
ClassPair<K, A> classPair = new ClassPair<>((Class<K>) identifier.getClass(), (Class<A>) value.getClass());
List<Mapper> candidates = this.mappers.get(classPair);
return candidates
.stream()
.filter(mapper -> Objects.equals(mapper.typeB, toType))
.findAny()
.map(mapper -> toType.cast(mapper.func.apply(identifier, value)));
}
@Override
public <K, A, B> DataService registerMapper(Class<K> identifierType, Class<A> from, Class<B> to, BiFunction<K, A, B> mapper) {
ClassPair<K, A> classPair = new ClassPair<>(identifierType, from);
@ -80,8 +91,8 @@ public class DataSvc implements DataService {
}
@Override
public <K1, K2, A, B> DataService registerMapper(Class<K1> fromIdentifier, Class<A> from, Class<K2> toIdentifier, Class<B> to, TriConsumer<K1, A, BiConsumer<K2, B>> mapper) {
ClassPair<K1, A> classPair = new ClassPair<>(fromIdentifier, from);
public <K, Y, A, B> DataService registerMapper(Class<K> fromIdentifier, Class<A> from, Class<Y> toIdentifier, Class<B> to, TriConsumer<K, A, BiConsumer<Y, B>> mapper) {
ClassPair<K, A> classPair = new ClassPair<>(fromIdentifier, from);
sinks.putOne(classPair, (id, value) -> mapper.accept(fromIdentifier.cast(id), from.cast(value), this::push));
return this;
}
@ -107,7 +118,7 @@ public class DataSvc implements DataService {
}
@Override
public <T> Optional<T> pull(Class<T> type) {
public <T> Optional<T> pullWithoutId(Class<T> type) {
return Optional.ofNullable(noIdentifierPullSources.get(type))
.map(Supplier::get)
.map(type::cast);

View File

@ -0,0 +1,24 @@
/*
* 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.exceptions;
public class MissingPipelineException extends IllegalStateException {
public MissingPipelineException() {
super("A data service pipeline is missing!");
}
}

View File

@ -0,0 +1,59 @@
/*
* 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.cache;
import com.djrapitops.plan.gathering.domain.event.JoinAddress;
import com.djrapitops.plan.gathering.domain.event.PlayerLeave;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
@Singleton
public class JoinAddressCache {
private final Map<UUID, String> joinAddresses;
@Inject
public JoinAddressCache() {
joinAddresses = new HashMap<>();
}
public void put(UUID playerUUID, JoinAddress joinAddress) {
put(playerUUID, joinAddress.getAddress());
}
public void put(UUID playerUUID, String joinAddress) {
joinAddresses.put(playerUUID, joinAddress);
}
public Optional<JoinAddress> get(UUID playerUUID) {
return Optional.ofNullable(joinAddresses.get(playerUUID))
.map(JoinAddress::new);
}
public void remove(UUID playerUUID, PlayerLeave leave) {
remove(playerUUID);
}
public void remove(UUID playerUUID) {
joinAddresses.remove(playerUUID);
}
}

View File

@ -18,6 +18,7 @@ package com.djrapitops.plan.gathering.cache;
import com.djrapitops.plan.gathering.domain.ActiveSession;
import com.djrapitops.plan.gathering.domain.FinishedSession;
import com.djrapitops.plan.gathering.domain.event.PlayerLeave;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -97,6 +98,10 @@ public class SessionCache {
return Optional.of(activeSession.toFinishedSession(time));
}
public Optional<FinishedSession> endSession(UUID playerUUID, PlayerLeave leave) {
return endSession(playerUUID, leave.getTime());
}
public Optional<FinishedSession> endSession(UUID playerUUID, long time) {
return endSession(playerUUID, time, ACTIVE_SESSIONS.get(playerUUID));
}

View File

@ -46,7 +46,9 @@ public class ActiveSession {
}
public static ActiveSession fromPlayerJoin(PlayerJoin join) {
return new ActiveSession(join.getPlayerUUID(), join.getServerUUID(), join.getTime(), join.getWorld(), join.getGameMode());
return new ActiveSession(join.getPlayerUUID(), join.getServerUUID(), join.getTime(),
join.getPlayerMetadata().getWorld().orElse("Unspecified"),
join.getPlayerMetadata().getGameMode().orElse("Unknown"));
}
public FinishedSession toFinishedSessionFromStillActive() {

View File

@ -0,0 +1,114 @@
/*
* 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.domain;
import java.net.InetAddress;
import java.util.Optional;
public class PlayerMetadata {
private final String playerName;
private final String displayName;
private final String joinAddress;
private final InetAddress ipAddress;
private final String world;
private final String gameMode;
public PlayerMetadata(String playerName, String displayName, String joinAddress, InetAddress ipAddress, String world, String gameMode) {
this.playerName = playerName;
this.displayName = displayName;
this.joinAddress = joinAddress;
this.ipAddress = ipAddress;
this.world = world;
this.gameMode = gameMode;
}
public static Builder builder() {
return new Builder();
}
public String getPlayerName() {
return playerName;
}
public String getDisplayName() {
return displayName;
}
public Optional<String> getJoinAddress() {
return Optional.ofNullable(joinAddress);
}
public Optional<InetAddress> getIpAddress() {
return Optional.ofNullable(ipAddress);
}
public Optional<String> getWorld() {
return Optional.ofNullable(world);
}
public Optional<String> getGameMode() {
return Optional.ofNullable(gameMode);
}
public static final class Builder {
private String playerName;
private String displayName;
private String joinAddress;
private InetAddress ipAddress;
private String world;
private String gameMode;
private Builder() {}
public static Builder aPlayerMetadata() {return new Builder();}
public Builder playerName(String playerName) {
this.playerName = playerName;
return this;
}
public Builder displayName(String displayName) {
this.displayName = displayName;
return this;
}
public Builder joinAddress(String joinAddress) {
this.joinAddress = joinAddress;
return this;
}
public Builder ipAddress(InetAddress ipAddress) {
this.ipAddress = ipAddress;
return this;
}
public Builder world(String world) {
this.world = world;
return this;
}
public Builder gameMode(String gameMode) {
this.gameMode = gameMode;
return this;
}
public PlayerMetadata build() {return new PlayerMetadata(playerName, displayName, joinAddress, ipAddress, world, gameMode);}
}
}

View File

@ -0,0 +1,36 @@
/*
* 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.domain.event;
public class JoinAddress {
private final String address;
public JoinAddress(String address) {
this.address = address;
}
public String getAddress() {
return address;
}
@Override
public String toString() {
return "JoinAddress{" +
"address='" + address + '\'' +
'}';
}
}

View File

@ -0,0 +1,89 @@
/*
* 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.domain.event;
import com.djrapitops.plan.gathering.domain.PlayerMetadata;
import java.util.UUID;
public class MobKill {
private final UUID playerUUID;
private final PlayerMetadata playerMetadata;
private final String mobType;
private final long time;
public MobKill(UUID playerUUID, PlayerMetadata playerMetadata, String mobType, long time) {
this.playerUUID = playerUUID;
this.playerMetadata = playerMetadata;
this.mobType = mobType;
this.time = time;
}
public static Builder builder() {
return new Builder();
}
public UUID getPlayerUUID() {
return playerUUID;
}
public PlayerMetadata getPlayerMetadata() {
return playerMetadata;
}
public String getMobType() {
return mobType;
}
public long getTime() {
return time;
}
public static final class Builder {
private UUID playerUUID;
private PlayerMetadata playerMetadata;
private String mobType;
private long time;
private Builder() {}
public static Builder aMobKill() {return new Builder();}
public Builder playerUUID(UUID playerUUID) {
this.playerUUID = playerUUID;
return this;
}
public Builder playerMetadata(PlayerMetadata playerMetadata) {
this.playerMetadata = playerMetadata;
return this;
}
public Builder mobType(String mobType) {
this.mobType = mobType;
return this;
}
public Builder time(long time) {
this.time = time;
return this;
}
public MobKill build() {return new MobKill(playerUUID, playerMetadata, mobType, time);}
}
}

View File

@ -16,68 +16,76 @@
*/
package com.djrapitops.plan.gathering.domain.event;
import com.djrapitops.plan.gathering.domain.PlayerMetadata;
import com.djrapitops.plan.identification.ServerUUID;
import java.net.InetAddress;
import java.util.UUID;
public class PlayerJoin {
private final UUID playerUUID;
private final String playerName;
private final String displayName;
private final InetAddress ipAddress;
private final ServerUUID serverUUID;
private final String world;
private final String gameMode;
private final PlayerMetadata playerMetadata;
private final long time;
public PlayerJoin(
UUID playerUUID, String playerName, String displayName, InetAddress ipAddress,
ServerUUID serverUUID, String world, String gameMode,
long time
) {
public PlayerJoin(UUID playerUUID, ServerUUID serverUUID, PlayerMetadata playerMetadata, long time) {
this.playerUUID = playerUUID;
this.playerName = playerName;
this.displayName = displayName;
this.ipAddress = ipAddress;
this.serverUUID = serverUUID;
this.world = world;
this.gameMode = gameMode;
this.playerMetadata = playerMetadata;
this.time = time;
}
public static Builder builder() {
return new Builder();
}
public UUID getPlayerUUID() {
return playerUUID;
}
public String getPlayerName() {
return playerName;
}
public String getDisplayName() {
return displayName;
}
public InetAddress getIpAddress() {
return ipAddress;
}
public ServerUUID getServerUUID() {
return serverUUID;
}
public String getWorld() {
return world;
}
public String getGameMode() {
return gameMode;
public PlayerMetadata getPlayerMetadata() {
return playerMetadata;
}
public long getTime() {
return time;
}
public static final class Builder {
private UUID playerUUID;
private ServerUUID serverUUID;
private PlayerMetadata playerMetadata;
private long time;
private Builder() {}
public static Builder aPlayerJoin() {return new Builder();}
public Builder playerUUID(UUID playerUUID) {
this.playerUUID = playerUUID;
return this;
}
public Builder serverUUID(ServerUUID serverUUID) {
this.serverUUID = serverUUID;
return this;
}
public Builder playerMetadata(PlayerMetadata playerMetadata) {
this.playerMetadata = playerMetadata;
return this;
}
public Builder time(long time) {
this.time = time;
return this;
}
public PlayerJoin build() {return new PlayerJoin(playerUUID, serverUUID, playerMetadata, time);}
}
}

View File

@ -0,0 +1,91 @@
/*
* 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.domain.event;
import com.djrapitops.plan.gathering.domain.PlayerMetadata;
import com.djrapitops.plan.identification.ServerUUID;
import java.util.UUID;
public class PlayerLeave {
private final UUID playerUUID;
private final ServerUUID serverUUID;
private final PlayerMetadata playerMetadata;
private final long time;
public PlayerLeave(UUID playerUUID, ServerUUID serverUUID, PlayerMetadata playerMetadata, long time) {
this.playerUUID = playerUUID;
this.serverUUID = serverUUID;
this.playerMetadata = playerMetadata;
this.time = time;
}
public static Builder builder() {
return new Builder();
}
public UUID getPlayerUUID() {
return playerUUID;
}
public ServerUUID getServerUUID() {
return serverUUID;
}
public PlayerMetadata getPlayerMetadata() {
return playerMetadata;
}
public long getTime() {
return time;
}
public static final class Builder {
private UUID playerUUID;
private ServerUUID serverUUID;
private PlayerMetadata playerMetadata;
private long time;
private Builder() {}
public static Builder aPlayerLeave() {return new Builder();}
public Builder playerUUID(UUID playerUUID) {
this.playerUUID = playerUUID;
return this;
}
public Builder serverUUID(ServerUUID serverUUID) {
this.serverUUID = serverUUID;
return this;
}
public Builder playerMetadata(PlayerMetadata playerMetadata) {
this.playerMetadata = playerMetadata;
return this;
}
public Builder time(long time) {
this.time = time;
return this;
}
public PlayerLeave build() {return new PlayerLeave(playerUUID, serverUUID, playerMetadata, time);}
}
}

View File

@ -17,9 +17,14 @@
package com.djrapitops.plan.modules;
import com.djrapitops.plan.DataService;
import com.djrapitops.plan.gathering.cache.JoinAddressCache;
import com.djrapitops.plan.gathering.cache.SessionCache;
import com.djrapitops.plan.gathering.domain.ActiveSession;
import com.djrapitops.plan.gathering.domain.*;
import com.djrapitops.plan.gathering.domain.event.JoinAddress;
import com.djrapitops.plan.gathering.domain.event.MobKill;
import com.djrapitops.plan.gathering.domain.event.PlayerJoin;
import com.djrapitops.plan.gathering.domain.event.PlayerLeave;
import com.djrapitops.plan.storage.database.transactions.events.SessionEndTransaction;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoSet;
@ -39,4 +44,54 @@ public class DataPipelineModule {
.registerSink(UUID.class, ActiveSession.class, sessionCache::cacheSession);
}
@Provides
@Singleton
@IntoSet
DataService.Pipeline joinAddress(JoinAddressCache joinAddressCache) {
return service -> service
.registerSink(UUID.class, JoinAddress.class, joinAddressCache::put)
.registerOptionalPullSource(UUID.class, JoinAddress.class, joinAddressCache::get)
.registerSink(UUID.class, PlayerLeave.class, joinAddressCache::remove);
}
@Provides
@Singleton
@IntoSet
DataService.Pipeline duringSession() {
return service -> service
.registerOptionalPullSource(UUID.class, ActiveSession.class, SessionCache::getCachedSession)
.registerOptionalPullSource(UUID.class, WorldTimes.class, uuid ->
service.pull(ActiveSession.class, uuid)
.map(ActiveSession::getExtraData)
.flatMap(extra -> extra.get(WorldTimes.class)))
.registerOptionalPullSource(UUID.class, MobKillCounter.class, uuid ->
service.pull(ActiveSession.class, uuid)
.map(ActiveSession::getExtraData)
.flatMap(extra -> extra.get(MobKillCounter.class)))
.registerOptionalPullSource(UUID.class, DeathCounter.class, uuid ->
service.pull(ActiveSession.class, uuid)
.map(ActiveSession::getExtraData)
.flatMap(extra -> extra.get(DeathCounter.class)))
.registerOptionalPullSource(UUID.class, PlayerKills.class, uuid ->
service.pull(ActiveSession.class, uuid)
.map(ActiveSession::getExtraData)
.flatMap(extra -> extra.get(PlayerKills.class)))
.registerSink(UUID.class, MobKill.class, (uuid, kill) -> {
service.pull(MobKillCounter.class, uuid).ifPresent(Counter::add);
})
.registerSink(UUID.class, PlayerKill.class, (uuid, kill) -> {
service.pull(PlayerKills.class, kill.getKiller().getUuid()).ifPresent(playerKills -> playerKills.add(kill));
service.pull(DeathCounter.class, kill.getVictim().getUuid()).ifPresent(Counter::add);
});
}
@Provides
@Singleton
@IntoSet
DataService.Pipeline playerLeaveToSession(SessionCache sessionCache) {
return service -> service
.registerOptionalMapper(UUID.class, PlayerLeave.class, FinishedSession.class, sessionCache::endSession)
.registerDatabaseSink(UUID.class, FinishedSession.class, SessionEndTransaction::new);
}
}

View File

@ -20,6 +20,8 @@ import com.djrapitops.plan.gathering.domain.FinishedSession;
import com.djrapitops.plan.storage.database.queries.DataStoreQueries;
import com.djrapitops.plan.storage.database.transactions.Transaction;
import java.util.UUID;
/**
* Transaction for storing a session after a session has ended.
*
@ -29,6 +31,10 @@ public class SessionEndTransaction extends Transaction {
private final FinishedSession session;
public SessionEndTransaction(UUID playerUUID, FinishedSession session) {
this(session);
}
public SessionEndTransaction(FinishedSession session) {
this.session = session;
}