/*
* 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.profile;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableList;
import org.lanternpowered.server.game.Lantern;
import org.spongepowered.api.profile.GameProfile;
import org.spongepowered.api.profile.GameProfileCache;
import org.spongepowered.api.profile.GameProfileManager;
import org.spongepowered.api.profile.ProfileNotFoundException;
import org.spongepowered.api.profile.property.ProfileProperty;
import org.spongepowered.api.util.GuavaCollectors;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import javax.annotation.Nullable;
public final class LanternGameProfileManager implements GameProfileManager {
// The game profile cache
private GameProfileCache gameProfileCache;
// The default game profile cache
private final LanternGameProfileCache defaultGameProfileCache;
public LanternGameProfileManager(Path cacheFile) {
this.defaultGameProfileCache = new LanternGameProfileCache(cacheFile);
this.gameProfileCache = this.defaultGameProfileCache;
}
@Override
public GameProfile createProfile(UUID uniqueId, @Nullable String name) {
return new LanternGameProfile(uniqueId, name);
}
@Override
public ProfileProperty createProfileProperty(String name, String value, @Nullable String signature) {
return new LanternProfileProperty(name, value, signature);
}
private GameProfile getById(UUID uniqueId, boolean useCache, boolean signed) throws Exception {
if (useCache) {
final Optional<GameProfile> optProfile = this.gameProfileCache.getOrLookupById(uniqueId);
if (optProfile.isPresent()) {
return optProfile.get();
}
}
return GameProfileQuery.queryProfileByUUID(uniqueId, signed);
}
@Override
public CompletableFuture<GameProfile> get(UUID uniqueId, boolean useCache) {
checkNotNull(uniqueId, "uniqueId");
return Lantern.getScheduler().submitAsyncTask(() -> this.getById(uniqueId, useCache, true));
}
@Override
public CompletableFuture<Collection<GameProfile>> getAllById(Iterable<UUID> uniqueIds, boolean useCache) {
checkNotNull(uniqueIds, "uniqueIds");
return Lantern.getScheduler().submitAsyncTask(() -> {
final ImmutableList.Builder<GameProfile> builder = ImmutableList.builder();
for (UUID uniqueId : uniqueIds) {
builder.add(getById(uniqueId, useCache, true));
}
return builder.build();
});
}
@Override
public CompletableFuture<GameProfile> get(String name, boolean useCache) {
checkNotNull(name, "name");
return Lantern.getScheduler().submitAsyncTask(() -> {
if (useCache) {
final Optional<GameProfile> optProfile = this.gameProfileCache.getOrLookupByName(name);
if (optProfile.isPresent()) {
return optProfile.get();
} else {
throw new ProfileNotFoundException("Unable to find a profile for the name: " + name);
}
}
final Map<String, UUID> result = GameProfileQuery.queryUUIDByName(Collections.singletonList(name));
if (!result.containsKey(name)) {
throw new ProfileNotFoundException("Unable to find a profile for the name: " + name);
}
return GameProfileQuery.queryProfileByUUID(result.get(name), true);
});
}
@Override
public CompletableFuture<Collection<GameProfile>> getAllByName(Iterable<String> names, boolean useCache) {
checkNotNull(names, "names");
return Lantern.getScheduler().submitAsyncTask(() -> {
if (useCache) {
final Map<String, Optional<GameProfile>> profiles = this.gameProfileCache.getOrLookupByNames(names);
return profiles.values().stream().filter(Optional::isPresent).map(Optional::get).collect(GuavaCollectors.toImmutableSet());
}
final ImmutableList.Builder<GameProfile> builder = ImmutableList.builder();
final Map<String, UUID> results = GameProfileQuery.queryUUIDByName(names);
for (String name : names) {
if (!results.containsKey(name)) {
throw new ProfileNotFoundException("Unable to find a profile with the name: " + name);
}
builder.add(getById(results.get(name), false, true));
}
return builder.build();
});
}
@Override
public CompletableFuture<GameProfile> fill(GameProfile profile, boolean signed, boolean useCache) {
checkNotNull(profile, "profile");
return Lantern.getScheduler().submitAsyncTask(() -> {
if (useCache) {
final Optional<GameProfile> optProfile = this.gameProfileCache.fillProfile(profile, signed);
if (optProfile.isPresent()) {
return optProfile.get();
}
}
final GameProfile gameProfile = this.getById(profile.getUniqueId(), useCache, signed);
((LanternGameProfile) profile).setName(gameProfile.getName().get());
profile.getPropertyMap().putAll(gameProfile.getPropertyMap());
return profile;
});
}
@Override
public GameProfileCache getCache() {
return this.gameProfileCache;
}
@Override
public void setCache(GameProfileCache cache) {
this.gameProfileCache = checkNotNull(cache, "cache");
}
@Override
public LanternGameProfileCache getDefaultCache() {
return this.defaultGameProfileCache;
}
}