/*
* This file is part of LanternServer, licensed under the MIT License (MIT).
*
* Copyright (c) LanternPowered <https://www.lanternpowered.org>
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the Software), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.lanternpowered.server.statistic;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.lanternpowered.server.game.registry.type.statistic.StatisticRegistryModule;
import org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayOutStatistics;
import org.lanternpowered.server.statistic.achievement.IAchievement;
import org.spongepowered.api.statistic.Statistic;
import org.spongepowered.api.statistic.achievement.Achievement;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
public final class StatisticMap {
private static final Gson GSON = new Gson();
private final Map<String, StatisticEntry> statisticEntries = new ConcurrentHashMap<>();
public StatisticEntry get(Statistic statistic) {
return this.statisticEntries.computeIfAbsent(((LanternStatistic) statistic).getInternalId(),
id -> new StatisticEntry((LanternStatistic) statistic));
}
public Map<Statistic, Long> getStatisticValues() {
final Map<Statistic, Long> map = new HashMap<>();
for (Map.Entry<String, StatisticEntry> entry : this.statisticEntries.entrySet()) {
final LanternStatistic statistic = entry.getValue().getStatistic();
if (statistic != null) {
map.put(statistic, entry.getValue().get());
}
}
return map;
}
public void setStatisticValues(Map<Statistic, Long> values) {
final Set<StatisticEntry> restEntries = new HashSet<>(this.statisticEntries.values());
for (Map.Entry<Statistic, Long> entry : values.entrySet()) {
final StatisticEntry statisticEntry = get(entry.getKey());
statisticEntry.set(entry.getValue());
restEntries.remove(statisticEntry);
}
for (StatisticEntry entry : restEntries) {
entry.set(0);
}
}
private StatisticEntry get(String statistic) {
return this.statisticEntries.computeIfAbsent(statistic,
id -> new StatisticEntry((LanternStatistic) StatisticRegistryModule.get().getByInternalId(statistic).orElse(null)));
}
@Nullable
public MessagePlayOutStatistics createAchievementsMessage(boolean initial) {
Set<MessagePlayOutStatistics.Entry> entries = initial ? new HashSet<>() : null;
for (Map.Entry<String, StatisticEntry> entry : this.statisticEntries.entrySet()) {
final LanternStatistic statistic = entry.getValue().getStatistic();
if (!(statistic instanceof Achievement) || !entry.getValue().isDirty(true)) {
continue;
}
final IAchievement achievement = (IAchievement) statistic;
final long value = entry.getValue().get();
if (value >= achievement.getStatisticTargetValue()) {
if (entries == null) {
entries = new HashSet<>();
}
entries.add(new MessagePlayOutStatistics.Entry(((LanternStatistic) achievement).getInternalId(), (int) value));
}
}
return entries == null ? null : new MessagePlayOutStatistics(entries);
}
public MessagePlayOutStatistics createStatisticsMessage() {
return new MessagePlayOutStatistics(this.statisticEntries.entrySet().stream()
.filter(entry -> entry.getValue().getStatistic() instanceof Achievement && entry.getValue().isDirty(true))
.map(entry -> new MessagePlayOutStatistics.Entry(entry.getKey(), (int) entry.getValue().get()))
.collect(Collectors.toSet()));
}
public void save(Path path) throws IOException {
if (!Files.exists(path.getParent())) {
Files.createDirectories(path.getParent());
}
try (final BufferedWriter writer = Files.newBufferedWriter(path)) {
final JsonObject object = new JsonObject();
for (Map.Entry<String, StatisticEntry> entry : this.statisticEntries.entrySet()) {
final long value = entry.getValue().get();
if (value != 0) {
object.addProperty(entry.getKey(), value);
}
}
GSON.toJson(object, writer);
writer.flush();
}
}
public void load(Path path) throws IOException {
try (final BufferedReader reader = Files.newBufferedReader(path)) {
this.statisticEntries.clear();
final JsonObject object = GSON.fromJson(reader, JsonObject.class);
for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
get(entry.getKey()).set(entry.getValue().getAsLong());
}
}
}
}