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

Commit c06e44f

Browse files
committed
Resolve map author names locally
1 parent 8a79575 commit c06e44f

File tree

21 files changed

+324
-147
lines changed

21 files changed

+324
-147
lines changed

API/api/src/main/java/tc/oc/api/docs/virtual/MapDoc.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.util.List;
66
import java.util.Set;
77
import java.util.UUID;
8+
import java.util.stream.Stream;
89
import javax.annotation.Nonnull;
910
import javax.annotation.Nullable;
1011

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

54+
@Serialize(false)
55+
default Stream<UUID> authorAndContributorUuids() {
56+
return Stream.concat(author_uuids().stream(),
57+
contributor_uuids().stream());
58+
}
59+
5360
@Serialize
5461
interface Team extends Model {
5562
@Nonnull String name();

API/api/src/main/java/tc/oc/api/maps/MapService.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,8 @@ public interface MapService extends ModelService<MapDoc, MapDoc> {
1313

1414
ListenableFuture<MapRatingsResponse> getRatings(MapRatingsRequest request);
1515

16-
ListenableFuture<MapUpdateMultiResponse> updateMapsAndLookupAuthors(Collection<? extends MapDoc> maps);
16+
/**
17+
* Send map updates to the backend, and retrieve data about map contributors.
18+
*/
19+
UpdateMapsResponse updateMaps(Collection<? extends MapDoc> maps);
1720
}

API/api/src/main/java/tc/oc/api/maps/NullMapService.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.google.common.util.concurrent.ListenableFuture;
88
import tc.oc.api.docs.MapRating;
99
import tc.oc.api.docs.virtual.MapDoc;
10+
import tc.oc.api.message.types.UpdateMultiResponse;
1011
import tc.oc.api.model.NullModelService;
1112

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

2425
@Override
25-
public ListenableFuture<MapUpdateMultiResponse> updateMapsAndLookupAuthors(Collection<? extends MapDoc> maps) {
26-
return Futures.immediateFuture(new MapUpdateMultiResponse(Collections.emptyMap()));
26+
public UpdateMapsResponse updateMaps(Collection<? extends MapDoc> maps) {
27+
return new UpdateMapsResponse(
28+
Futures.immediateFuture(UpdateMultiResponse.EMPTY),
29+
Collections.emptyMap()
30+
);
2731
}
2832
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package tc.oc.api.maps;
2+
3+
import java.util.Collection;
4+
import java.util.Map;
5+
import java.util.UUID;
6+
7+
import com.google.common.util.concurrent.ListenableFuture;
8+
import tc.oc.api.docs.virtual.UserDoc;
9+
import tc.oc.api.message.types.UpdateMultiResponse;
10+
11+
/**
12+
* Result of {@link MapService#updateMaps(Collection)}
13+
*/
14+
public class UpdateMapsResponse {
15+
16+
private final ListenableFuture<UpdateMultiResponse> maps;
17+
private final Map<UUID, ListenableFuture<UserDoc.Identity>> authors;
18+
19+
public UpdateMapsResponse(ListenableFuture<UpdateMultiResponse> maps, Map<UUID, ListenableFuture<UserDoc.Identity>> authors) {
20+
this.maps = maps;
21+
this.authors = authors;
22+
}
23+
24+
/**
25+
* Result of updating all the maps
26+
*/
27+
public ListenableFuture<UpdateMultiResponse> maps() {
28+
return maps;
29+
}
30+
31+
/**
32+
* Result of each individual map contributor lookup,
33+
* which may not all arrive at the same time.
34+
*/
35+
public Map<UUID, ListenableFuture<UserDoc.Identity>> authors() {
36+
return authors;
37+
}
38+
}

API/api/src/main/java/tc/oc/api/users/UserSearchRequest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import tc.oc.api.annotations.Serialize;
66
import tc.oc.api.docs.PlayerId;
77
import tc.oc.api.docs.virtual.Document;
8+
import tc.oc.minecraft.api.user.UserUtils;
89

910
public class UserSearchRequest implements Document {
1011
@Serialize public final String username;

API/api/src/main/java/tc/oc/api/users/UserUtils.java

Lines changed: 0 additions & 10 deletions
This file was deleted.

API/minecraft/src/main/java/tc/oc/api/minecraft/maps/LocalMapService.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import java.util.Collection;
44
import java.util.Collections;
5-
import java.util.stream.Stream;
65
import javax.inject.Inject;
76
import javax.inject.Singleton;
87

@@ -13,16 +12,20 @@
1312
import tc.oc.api.maps.MapRatingsRequest;
1413
import tc.oc.api.maps.MapRatingsResponse;
1514
import tc.oc.api.maps.MapService;
16-
import tc.oc.api.maps.MapUpdateMultiResponse;
15+
import tc.oc.api.maps.UpdateMapsResponse;
16+
import tc.oc.api.message.types.UpdateMultiResponse;
1717
import tc.oc.api.minecraft.users.UserStore;
1818
import tc.oc.api.model.NullModelService;
19+
import tc.oc.api.users.UserService;
20+
import tc.oc.api.util.UUIDs;
1921
import tc.oc.commons.core.stream.Collectors;
2022
import tc.oc.minecraft.api.entity.Player;
2123

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

2527
@Inject private UserStore<Player> userStore;
28+
@Inject private UserService userService;
2629

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

3740
@Override
38-
public ListenableFuture<MapUpdateMultiResponse> updateMapsAndLookupAuthors(Collection<? extends MapDoc> maps) {
39-
return Futures.immediateFuture(new MapUpdateMultiResponse(
41+
public UpdateMapsResponse updateMaps(Collection<? extends MapDoc> maps) {
42+
return new UpdateMapsResponse(
43+
Futures.immediateFuture(UpdateMultiResponse.EMPTY),
4044
maps.stream()
41-
.flatMap(map -> Stream.concat(map.author_uuids().stream(),
42-
map.contributor_uuids().stream()))
43-
.collect(Collectors.mappingTo(uuid -> userStore.byUuid(uuid)
44-
.flatMap(userStore::user)
45-
.orElse(null)))
46-
));
45+
.flatMap(MapDoc::authorAndContributorUuids)
46+
.distinct()
47+
.collect(Collectors.mappingTo(uuid -> (ListenableFuture) userService.find(() -> UUIDs.normalize(uuid))))
48+
);
4749
}
4850
}

API/minecraft/src/main/java/tc/oc/api/minecraft/servers/LocalServerDocument.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import tc.oc.api.docs.virtual.MatchDoc;
1818
import tc.oc.api.docs.virtual.ServerDoc;
1919
import tc.oc.api.minecraft.config.MinecraftApiConfiguration;
20-
import tc.oc.minecraft.api.entity.OfflinePlayer;
20+
import tc.oc.minecraft.api.user.User;
2121
import tc.oc.minecraft.api.server.LocalServer;
2222

2323
@Singleton
@@ -162,8 +162,8 @@ public String settings_profile() {
162162
@Override
163163
public Map<UUID, String> operators() {
164164
final ImmutableMap.Builder<UUID, String> ops = ImmutableMap.builder();
165-
for(OfflinePlayer op : minecraftServer.getOperators()) {
166-
ops.put(op.getUniqueId(), op.getLastKnownName().orElse("Player"));
165+
for(User op : minecraftServer.getOperators()) {
166+
ops.put(op.getUniqueId(), op.name().orElse("Player"));
167167
}
168168
return ops.build();
169169
}

API/minecraft/src/main/java/tc/oc/api/minecraft/users/LocalUserDocument.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,24 @@
1515
import tc.oc.api.docs.User;
1616
import tc.oc.api.docs.virtual.UserDoc;
1717
import tc.oc.api.minecraft.servers.DefaultPermissions;
18-
import tc.oc.minecraft.api.entity.OfflinePlayer;
1918

2019
public class LocalUserDocument extends SimplePlayerId implements User {
2120

22-
private final OfflinePlayer player;
21+
private final UUID uuid;
22+
private final String ip;
2323

24-
public LocalUserDocument(OfflinePlayer player) {
25-
super(player.getUniqueId().toString(),
26-
player.getUniqueId().toString(),
27-
player.getLastKnownName().orElse(""));
24+
LocalUserDocument(UUID uuid, String name, String ip) {
25+
super(uuid.toString(), uuid.toString(), name);
26+
this.uuid = uuid;
27+
this.ip = ip;
28+
}
2829

29-
this.player = player;
30+
LocalUserDocument(tc.oc.minecraft.api.user.User user) {
31+
this(user.getUniqueId(),
32+
user.getName(),
33+
user.onlinePlayer()
34+
.map(p -> p.getAddress().getHostString())
35+
.orElse(""));
3036
}
3137

3238
@Override
@@ -41,7 +47,7 @@ public LocalUserDocument(OfflinePlayer player) {
4147

4248
@Override
4349
public UUID uuid() {
44-
return player.getUniqueId();
50+
return uuid;
4551
}
4652

4753
@Override
@@ -76,9 +82,7 @@ public int raindrops() {
7682

7783
@Override
7884
public String mc_last_sign_in_ip() {
79-
return player.onlinePlayer()
80-
.map(p -> p.getAddress().getHostString())
81-
.orElse("");
85+
return ip;
8286
}
8387

8488
@Override

API/minecraft/src/main/java/tc/oc/api/minecraft/users/LocalUserService.java

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,39 +30,43 @@
3030
import tc.oc.api.users.UserService;
3131
import tc.oc.api.users.UserUpdateResponse;
3232
import tc.oc.commons.core.concurrent.FutureUtils;
33-
import tc.oc.minecraft.api.entity.OfflinePlayer;
34-
import tc.oc.minecraft.api.server.LocalServer;
33+
import tc.oc.minecraft.api.user.UserFinder;
3534

3635
@Singleton
37-
public class LocalUserService extends NullModelService<User, UserDoc.Partial> implements UserService {
36+
class LocalUserService extends NullModelService<User, UserDoc.Partial> implements UserService {
3837

39-
@Inject private LocalServer minecraftServer;
4038
@Inject private LocalSessionFactory sessionFactory;
39+
@Inject private UserFinder userFinder;
4140

4241
@Override
4342
public ListenableFuture<User> find(UserId userId) {
44-
return Futures.immediateFuture(new LocalUserDocument(minecraftServer.getOfflinePlayer(UUID.fromString(userId.player_id()))));
43+
return FutureUtils.mapSync(
44+
userFinder.findUserAsync(UUID.fromString(userId.player_id())),
45+
user -> {
46+
if(user.hasValidId() && user.name().isPresent()) {
47+
return new LocalUserDocument(user);
48+
}
49+
throw new NotFound("No user with UUID " + userId.player_id());
50+
}
51+
);
4552
}
4653

4754
@Override
4855
public ListenableFuture<UserSearchResponse> search(UserSearchRequest request) {
49-
for(OfflinePlayer player : minecraftServer.getSavedPlayers()) {
50-
if(player.getLastKnownName()
51-
.filter(name -> name.equalsIgnoreCase(request.username))
52-
.isPresent()) {
53-
return Futures.immediateFuture(new UserSearchResponse(new LocalUserDocument(player),
54-
player.isOnline(),
55-
false,
56-
null,
57-
null));
56+
return FutureUtils.mapSync(
57+
userFinder.findUserAsync(request.username),
58+
user -> {
59+
if(user.hasValidId()) {
60+
return new UserSearchResponse(new LocalUserDocument(user), user.isOnline(), false, null, null);
61+
}
62+
throw new NotFound("No user named '" + request.username + "'");
5863
}
59-
}
60-
return Futures.immediateFailedFuture(new NotFound("No user named '" + request.username + "'", null));
64+
);
6165
}
6266

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

0 commit comments

Comments
 (0)