Skip to content
This repository has been archived by the owner on Jul 20, 2020. It is now read-only.

Commit

Permalink
Resolve map author names locally
Browse files Browse the repository at this point in the history
  • Loading branch information
jedediah committed Feb 7, 2017
1 parent 8a79575 commit c06e44f
Show file tree
Hide file tree
Showing 21 changed files with 324 additions and 147 deletions.
7 changes: 7 additions & 0 deletions API/api/src/main/java/tc/oc/api/docs/virtual/MapDoc.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

Expand Down Expand Up @@ -50,6 +51,12 @@ enum Gamemode { tdm, ctw, ctf, dtc, dtm, ad, koth, blitz, rage, scorebox, arcade
Collection<UUID> author_uuids();
Collection<UUID> contributor_uuids();

@Serialize(false)
default Stream<UUID> authorAndContributorUuids() {
return Stream.concat(author_uuids().stream(),
contributor_uuids().stream());
}

@Serialize
interface Team extends Model {
@Nonnull String name();
Expand Down
5 changes: 4 additions & 1 deletion API/api/src/main/java/tc/oc/api/maps/MapService.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ public interface MapService extends ModelService<MapDoc, MapDoc> {

ListenableFuture<MapRatingsResponse> getRatings(MapRatingsRequest request);

ListenableFuture<MapUpdateMultiResponse> updateMapsAndLookupAuthors(Collection<? extends MapDoc> maps);
/**
* Send map updates to the backend, and retrieve data about map contributors.
*/
UpdateMapsResponse updateMaps(Collection<? extends MapDoc> maps);
}
8 changes: 6 additions & 2 deletions API/api/src/main/java/tc/oc/api/maps/NullMapService.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.google.common.util.concurrent.ListenableFuture;
import tc.oc.api.docs.MapRating;
import tc.oc.api.docs.virtual.MapDoc;
import tc.oc.api.message.types.UpdateMultiResponse;
import tc.oc.api.model.NullModelService;

public class NullMapService extends NullModelService<MapDoc, MapDoc> implements MapService {
Expand All @@ -22,7 +23,10 @@ public ListenableFuture<MapRatingsResponse> getRatings(MapRatingsRequest request
}

@Override
public ListenableFuture<MapUpdateMultiResponse> updateMapsAndLookupAuthors(Collection<? extends MapDoc> maps) {
return Futures.immediateFuture(new MapUpdateMultiResponse(Collections.emptyMap()));
public UpdateMapsResponse updateMaps(Collection<? extends MapDoc> maps) {
return new UpdateMapsResponse(
Futures.immediateFuture(UpdateMultiResponse.EMPTY),
Collections.emptyMap()
);
}
}
38 changes: 38 additions & 0 deletions API/api/src/main/java/tc/oc/api/maps/UpdateMapsResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package tc.oc.api.maps;

import java.util.Collection;
import java.util.Map;
import java.util.UUID;

import com.google.common.util.concurrent.ListenableFuture;
import tc.oc.api.docs.virtual.UserDoc;
import tc.oc.api.message.types.UpdateMultiResponse;

/**
* Result of {@link MapService#updateMaps(Collection)}
*/
public class UpdateMapsResponse {

private final ListenableFuture<UpdateMultiResponse> maps;
private final Map<UUID, ListenableFuture<UserDoc.Identity>> authors;

public UpdateMapsResponse(ListenableFuture<UpdateMultiResponse> maps, Map<UUID, ListenableFuture<UserDoc.Identity>> authors) {
this.maps = maps;
this.authors = authors;
}

/**
* Result of updating all the maps
*/
public ListenableFuture<UpdateMultiResponse> maps() {
return maps;
}

/**
* Result of each individual map contributor lookup,
* which may not all arrive at the same time.
*/
public Map<UUID, ListenableFuture<UserDoc.Identity>> authors() {
return authors;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import tc.oc.api.annotations.Serialize;
import tc.oc.api.docs.PlayerId;
import tc.oc.api.docs.virtual.Document;
import tc.oc.minecraft.api.user.UserUtils;

public class UserSearchRequest implements Document {
@Serialize public final String username;
Expand Down
10 changes: 0 additions & 10 deletions API/api/src/main/java/tc/oc/api/users/UserUtils.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.util.Collection;
import java.util.Collections;
import java.util.stream.Stream;
import javax.inject.Inject;
import javax.inject.Singleton;

Expand All @@ -13,16 +12,20 @@
import tc.oc.api.maps.MapRatingsRequest;
import tc.oc.api.maps.MapRatingsResponse;
import tc.oc.api.maps.MapService;
import tc.oc.api.maps.MapUpdateMultiResponse;
import tc.oc.api.maps.UpdateMapsResponse;
import tc.oc.api.message.types.UpdateMultiResponse;
import tc.oc.api.minecraft.users.UserStore;
import tc.oc.api.model.NullModelService;
import tc.oc.api.users.UserService;
import tc.oc.api.util.UUIDs;
import tc.oc.commons.core.stream.Collectors;
import tc.oc.minecraft.api.entity.Player;

@Singleton
public class LocalMapService extends NullModelService<MapDoc, MapDoc> implements MapService {

@Inject private UserStore<Player> userStore;
@Inject private UserService userService;

@Override
public ListenableFuture<?> rate(MapRating rating) {
Expand All @@ -35,14 +38,13 @@ public ListenableFuture<MapRatingsResponse> getRatings(MapRatingsRequest request
}

@Override
public ListenableFuture<MapUpdateMultiResponse> updateMapsAndLookupAuthors(Collection<? extends MapDoc> maps) {
return Futures.immediateFuture(new MapUpdateMultiResponse(
public UpdateMapsResponse updateMaps(Collection<? extends MapDoc> maps) {
return new UpdateMapsResponse(
Futures.immediateFuture(UpdateMultiResponse.EMPTY),
maps.stream()
.flatMap(map -> Stream.concat(map.author_uuids().stream(),
map.contributor_uuids().stream()))
.collect(Collectors.mappingTo(uuid -> userStore.byUuid(uuid)
.flatMap(userStore::user)
.orElse(null)))
));
.flatMap(MapDoc::authorAndContributorUuids)
.distinct()
.collect(Collectors.mappingTo(uuid -> (ListenableFuture) userService.find(() -> UUIDs.normalize(uuid))))
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import tc.oc.api.docs.virtual.MatchDoc;
import tc.oc.api.docs.virtual.ServerDoc;
import tc.oc.api.minecraft.config.MinecraftApiConfiguration;
import tc.oc.minecraft.api.entity.OfflinePlayer;
import tc.oc.minecraft.api.user.User;
import tc.oc.minecraft.api.server.LocalServer;

@Singleton
Expand Down Expand Up @@ -162,8 +162,8 @@ public String settings_profile() {
@Override
public Map<UUID, String> operators() {
final ImmutableMap.Builder<UUID, String> ops = ImmutableMap.builder();
for(OfflinePlayer op : minecraftServer.getOperators()) {
ops.put(op.getUniqueId(), op.getLastKnownName().orElse("Player"));
for(User op : minecraftServer.getOperators()) {
ops.put(op.getUniqueId(), op.name().orElse("Player"));
}
return ops.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,24 @@
import tc.oc.api.docs.User;
import tc.oc.api.docs.virtual.UserDoc;
import tc.oc.api.minecraft.servers.DefaultPermissions;
import tc.oc.minecraft.api.entity.OfflinePlayer;

public class LocalUserDocument extends SimplePlayerId implements User {

private final OfflinePlayer player;
private final UUID uuid;
private final String ip;

public LocalUserDocument(OfflinePlayer player) {
super(player.getUniqueId().toString(),
player.getUniqueId().toString(),
player.getLastKnownName().orElse(""));
LocalUserDocument(UUID uuid, String name, String ip) {
super(uuid.toString(), uuid.toString(), name);
this.uuid = uuid;
this.ip = ip;
}

this.player = player;
LocalUserDocument(tc.oc.minecraft.api.user.User user) {
this(user.getUniqueId(),
user.getName(),
user.onlinePlayer()
.map(p -> p.getAddress().getHostString())
.orElse(""));
}

@Override
Expand All @@ -41,7 +47,7 @@ public LocalUserDocument(OfflinePlayer player) {

@Override
public UUID uuid() {
return player.getUniqueId();
return uuid;
}

@Override
Expand Down Expand Up @@ -76,9 +82,7 @@ public int raindrops() {

@Override
public String mc_last_sign_in_ip() {
return player.onlinePlayer()
.map(p -> p.getAddress().getHostString())
.orElse("");
return ip;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,39 +30,43 @@
import tc.oc.api.users.UserService;
import tc.oc.api.users.UserUpdateResponse;
import tc.oc.commons.core.concurrent.FutureUtils;
import tc.oc.minecraft.api.entity.OfflinePlayer;
import tc.oc.minecraft.api.server.LocalServer;
import tc.oc.minecraft.api.user.UserFinder;

@Singleton
public class LocalUserService extends NullModelService<User, UserDoc.Partial> implements UserService {
class LocalUserService extends NullModelService<User, UserDoc.Partial> implements UserService {

@Inject private LocalServer minecraftServer;
@Inject private LocalSessionFactory sessionFactory;
@Inject private UserFinder userFinder;

@Override
public ListenableFuture<User> find(UserId userId) {
return Futures.immediateFuture(new LocalUserDocument(minecraftServer.getOfflinePlayer(UUID.fromString(userId.player_id()))));
return FutureUtils.mapSync(
userFinder.findUserAsync(UUID.fromString(userId.player_id())),
user -> {
if(user.hasValidId() && user.name().isPresent()) {
return new LocalUserDocument(user);
}
throw new NotFound("No user with UUID " + userId.player_id());
}
);
}

@Override
public ListenableFuture<UserSearchResponse> search(UserSearchRequest request) {
for(OfflinePlayer player : minecraftServer.getSavedPlayers()) {
if(player.getLastKnownName()
.filter(name -> name.equalsIgnoreCase(request.username))
.isPresent()) {
return Futures.immediateFuture(new UserSearchResponse(new LocalUserDocument(player),
player.isOnline(),
false,
null,
null));
return FutureUtils.mapSync(
userFinder.findUserAsync(request.username),
user -> {
if(user.hasValidId()) {
return new UserSearchResponse(new LocalUserDocument(user), user.isOnline(), false, null, null);
}
throw new NotFound("No user named '" + request.username + "'");
}
}
return Futures.immediateFailedFuture(new NotFound("No user named '" + request.username + "'", null));
);
}

@Override
public ListenableFuture<LoginResponse> login(LoginRequest request) {
final User user = new LocalUserDocument(minecraftServer.getOfflinePlayer(request.uuid));
final User user = new LocalUserDocument(request.uuid, request.username, request.ip.getHostAddress());
final Session session = request.start_session ? sessionFactory.newSession(user, request.ip)
: null;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package tc.oc.api.maps;
package tc.oc.api.ocn;

import java.util.Collections;
import java.util.Map;
Expand Down
24 changes: 21 additions & 3 deletions API/ocn/src/main/java/tc/oc/api/ocn/OCNMapService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@
import com.google.common.util.concurrent.ListenableFuture;
import tc.oc.api.docs.MapRating;
import tc.oc.api.docs.virtual.MapDoc;
import tc.oc.api.docs.virtual.UserDoc;
import tc.oc.api.exceptions.NotFound;
import tc.oc.api.http.HttpOption;
import tc.oc.api.maps.MapRatingsRequest;
import tc.oc.api.maps.MapRatingsResponse;
import tc.oc.api.maps.MapService;
import tc.oc.api.maps.MapUpdateMultiResponse;
import tc.oc.api.maps.UpdateMapsResponse;
import tc.oc.api.model.HttpModelService;
import tc.oc.commons.core.concurrent.FutureUtils;
import tc.oc.commons.core.stream.Collectors;

@Singleton
class OCNMapService extends HttpModelService<MapDoc, MapDoc> implements MapService {
Expand All @@ -24,7 +28,21 @@ public ListenableFuture<MapRatingsResponse> getRatings(MapRatingsRequest request
return this.client().post(memberUri(request.map_id, "get_ratings"), request, MapRatingsResponse.class, HttpOption.INFINITE_RETRY);
}

public ListenableFuture<MapUpdateMultiResponse> updateMapsAndLookupAuthors(Collection<? extends MapDoc> maps) {
return updateMulti(maps, MapUpdateMultiResponse.class);
public UpdateMapsResponse updateMaps(Collection<? extends MapDoc> maps) {
final ListenableFuture<MapUpdateMultiResponse> future = updateMulti(maps, MapUpdateMultiResponse.class);
return new UpdateMapsResponse(
(ListenableFuture) future,
maps.stream()
.flatMap(MapDoc::authorAndContributorUuids)
.distinct()
.collect(Collectors.mappingTo(uuid -> FutureUtils.mapSync(
future,
response -> {
final UserDoc.Identity user = response.users_by_uuid.get(uuid);
if(user != null) return user;
throw new NotFound();
}
)))
);
}
}
22 changes: 14 additions & 8 deletions PGM/src/main/java/tc/oc/pgm/map/MapDocument.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
Expand All @@ -25,6 +26,7 @@ public class MapDocument extends AbstractModel implements MapDoc {
private final InfoModule infoModule;
private final MapInfo info;
private final List<MapDoc.Team> teams;
private final List<UUID> authors, contributors;

@Inject private MapDocument(MapFolder folder, InfoModule infoModule, MapInfo info, List<TeamFactory> teams) {
this.folder = folder;
Expand All @@ -33,6 +35,16 @@ public class MapDocument extends AbstractModel implements MapDoc {
this.teams = teams.stream()
.map(TeamFactory::getDocument)
.collect(toImmutableList());

this.authors = info.authors.stream()
.map(Contributor::getUuid)
.filter(Objects::nonNull)
.collect(toImmutableList());

this.contributors = info.contributors.stream()
.map(Contributor::getUuid)
.filter(Objects::nonNull)
.collect(toImmutableList());
}

@Override
Expand Down Expand Up @@ -113,18 +125,12 @@ public List<Team> teams() {

@Override
public Collection<UUID> author_uuids() {
return info.authors.stream()
.map(Contributor::getUuid)
.filter(uuid -> uuid != null)
.collect(toImmutableList());
return authors;
}

@Override
public Collection<UUID> contributor_uuids() {
return info.contributors.stream()
.map(Contributor::getUuid)
.filter(uuid -> uuid != null)
.collect(toImmutableList());
return contributors;
}

}
Loading

0 comments on commit c06e44f

Please sign in to comment.