From 6c0da9e167d3aa7be893957982f167411faeddf4 Mon Sep 17 00:00:00 2001 From: Risto Lahtela <24460436+AuroraLS3@users.noreply.github.com> Date: Sun, 21 Nov 2021 20:10:27 +0200 Subject: [PATCH] Added some data pipelines, not in use yet --- .../bukkit/BukkitEventPipelineModule.java | 93 ++++++++++++++ .../java/com/djrapitops/plan/DataService.java | 18 ++- .../java/com/djrapitops/plan/DataSvc.java | 21 +++- .../exceptions/MissingPipelineException.java | 24 ++++ .../gathering/cache/JoinAddressCache.java | 59 +++++++++ .../plan/gathering/cache/SessionCache.java | 5 + .../plan/gathering/domain/ActiveSession.java | 4 +- .../plan/gathering/domain/PlayerMetadata.java | 114 ++++++++++++++++++ .../gathering/domain/event/JoinAddress.java | 36 ++++++ .../plan/gathering/domain/event/MobKill.java | 89 ++++++++++++++ .../gathering/domain/event/PlayerJoin.java | 78 ++++++------ .../gathering/domain/event/PlayerLeave.java | 91 ++++++++++++++ .../plan/modules/DataPipelineModule.java | 57 ++++++++- .../events/SessionEndTransaction.java | 6 + 14 files changed, 651 insertions(+), 44 deletions(-) create mode 100644 Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitEventPipelineModule.java create mode 100644 Plan/common/src/main/java/com/djrapitops/plan/exceptions/MissingPipelineException.java create mode 100644 Plan/common/src/main/java/com/djrapitops/plan/gathering/cache/JoinAddressCache.java create mode 100644 Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/PlayerMetadata.java create mode 100644 Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/JoinAddress.java create mode 100644 Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/MobKill.java create mode 100644 Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/PlayerLeave.java diff --git a/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitEventPipelineModule.java b/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitEventPipelineModule.java new file mode 100644 index 000000000..12759ff40 --- /dev/null +++ b/Plan/bukkit/src/main/java/com/djrapitops/plan/modules/bukkit/BukkitEventPipelineModule.java @@ -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 . + */ +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 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 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(); + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/DataService.java b/Plan/common/src/main/java/com/djrapitops/plan/DataService.java index d0f94875f..997579ec3 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/DataService.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/DataService.java @@ -34,11 +34,19 @@ public interface DataService { void push(K identifier, T value, Class type); + default DataService registerOptionalMapper(Class identifierType, Class from, Class to, BiFunction> mapper) { + return registerMapper(identifierType, from, to, (id, value) -> mapper.apply(id, value).orElse(null)); + } + DataService registerMapper(Class identifierType, Class from, Class to, BiFunction mapper); DataService registerMapper(Class identifierType, Class from, Class to, Function mapper); - DataService registerMapper(Class fromIdentifier, Class from, Class toIdentifier, Class to, TriConsumer> mapper); + default DataService registerDataServiceMapper(Class identifierType, Class from, Class to, BiFunction mapper) { + return registerMapper(identifierType, from, to, value -> mapper.apply(this, value)); + } + + DataService registerMapper(Class fromIdentifier, Class from, Class toIdentifier, Class to, TriConsumer> mapper); DataService registerSink(Class identifierType, Class type, BiConsumer consumer); @@ -46,16 +54,22 @@ public interface DataService { Optional pull(Class type, K identifier); - Optional pull(Class type); + Optional pullWithoutId(Class type); DataService registerPullSource(Class identifierType, Class type, Function source); + default DataService registerOptionalPullSource(Class identifierType, Class type, Function> source) { + return registerPullSource(identifierType, type, id -> source.apply(id).orElse(null)); + } + DataService registerDatabasePullSource(Class identifierType, Class type, Function> source); DataService registerPullSource(Class type, Supplier source); DataService registerDatabasePullSource(Class type, Supplier> source); + Optional map(K identifier, A value, Class toType); + interface Pipeline { void register(DataService service); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/DataSvc.java b/Plan/common/src/main/java/com/djrapitops/plan/DataSvc.java index 916d2b62b..16b921a57 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/DataSvc.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/DataSvc.java @@ -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 Optional map(K identifier, A value, Class toType) { + ClassPair classPair = new ClassPair<>((Class) identifier.getClass(), (Class) value.getClass()); + + List 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 DataService registerMapper(Class identifierType, Class from, Class to, BiFunction mapper) { ClassPair classPair = new ClassPair<>(identifierType, from); @@ -80,8 +91,8 @@ public class DataSvc implements DataService { } @Override - public DataService registerMapper(Class fromIdentifier, Class from, Class toIdentifier, Class to, TriConsumer> mapper) { - ClassPair classPair = new ClassPair<>(fromIdentifier, from); + public DataService registerMapper(Class fromIdentifier, Class from, Class toIdentifier, Class to, TriConsumer> mapper) { + ClassPair 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 Optional pull(Class type) { + public Optional pullWithoutId(Class type) { return Optional.ofNullable(noIdentifierPullSources.get(type)) .map(Supplier::get) .map(type::cast); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/exceptions/MissingPipelineException.java b/Plan/common/src/main/java/com/djrapitops/plan/exceptions/MissingPipelineException.java new file mode 100644 index 000000000..9f3728b10 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/exceptions/MissingPipelineException.java @@ -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 . + */ +package com.djrapitops.plan.exceptions; + +public class MissingPipelineException extends IllegalStateException { + + public MissingPipelineException() { + super("A data service pipeline is missing!"); + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/cache/JoinAddressCache.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/cache/JoinAddressCache.java new file mode 100644 index 000000000..e5b74b27d --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/cache/JoinAddressCache.java @@ -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 . + */ +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 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 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); + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/cache/SessionCache.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/cache/SessionCache.java index d9afef3a2..600d90ca1 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/gathering/cache/SessionCache.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/cache/SessionCache.java @@ -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 endSession(UUID playerUUID, PlayerLeave leave) { + return endSession(playerUUID, leave.getTime()); + } + public Optional endSession(UUID playerUUID, long time) { return endSession(playerUUID, time, ACTIVE_SESSIONS.get(playerUUID)); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/ActiveSession.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/ActiveSession.java index fc3fa4485..c45c3ec29 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/ActiveSession.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/ActiveSession.java @@ -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() { diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/PlayerMetadata.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/PlayerMetadata.java new file mode 100644 index 000000000..5a68173f0 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/PlayerMetadata.java @@ -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 . + */ +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 getJoinAddress() { + return Optional.ofNullable(joinAddress); + } + + public Optional getIpAddress() { + return Optional.ofNullable(ipAddress); + } + + public Optional getWorld() { + return Optional.ofNullable(world); + } + + public Optional 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);} + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/JoinAddress.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/JoinAddress.java new file mode 100644 index 000000000..15f5509b6 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/JoinAddress.java @@ -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 . + */ +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 + '\'' + + '}'; + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/MobKill.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/MobKill.java new file mode 100644 index 000000000..7ebe21f6f --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/MobKill.java @@ -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 . + */ +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);} + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/PlayerJoin.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/PlayerJoin.java index f86e37b9a..ecfa4bee6 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/PlayerJoin.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/PlayerJoin.java @@ -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);} + } } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/PlayerLeave.java b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/PlayerLeave.java new file mode 100644 index 000000000..afa570e36 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/gathering/domain/event/PlayerLeave.java @@ -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 . + */ +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);} + } +} diff --git a/Plan/common/src/main/java/com/djrapitops/plan/modules/DataPipelineModule.java b/Plan/common/src/main/java/com/djrapitops/plan/modules/DataPipelineModule.java index 92ed1062a..82d8587fc 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/modules/DataPipelineModule.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/modules/DataPipelineModule.java @@ -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); + } + } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/events/SessionEndTransaction.java b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/events/SessionEndTransaction.java index ab80cc47e..62d81253d 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/events/SessionEndTransaction.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/storage/database/transactions/events/SessionEndTransaction.java @@ -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; }