.
This commit is contained in:
parent
b6aff8497f
commit
ad4e00a6ab
19 changed files with 153 additions and 253 deletions
|
|
@ -36,7 +36,9 @@ dependencies {
|
||||||
api("org.spigotmc:spigot-api:1.21.11-R0.1-SNAPSHOT")
|
api("org.spigotmc:spigot-api:1.21.11-R0.1-SNAPSHOT")
|
||||||
api("net.kyori:adventure-platform-bukkit:4.4.1")
|
api("net.kyori:adventure-platform-bukkit:4.4.1")
|
||||||
|
|
||||||
api("de.kentoj:kencommandapi-core:1.2.0")
|
api("de.kentoj:kencommandapi-core:2.0.1")
|
||||||
|
implementation("de.kentoj:kencommandapi-bukkit:2.0.1")
|
||||||
|
api("de.kentoj:kencommandapi-bukkit:2.0.1")
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,11 @@
|
||||||
package de.kentoj.scrow.bukkit;
|
package de.kentoj.scrow.bukkit;
|
||||||
|
|
||||||
import com.mongodb.reactivestreams.client.MongoDatabase;
|
import com.mongodb.reactivestreams.client.MongoDatabase;
|
||||||
import de.kentoj.kencommandapi.api.KenCommandApi;
|
import de.kentoj.kencommandapi.BukkitKenCommandApi;
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
|
||||||
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
|
|
||||||
import de.kentoj.scrow.bukkit.friends.FriendsService;
|
import de.kentoj.scrow.bukkit.friends.FriendsService;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import reactor.core.scheduler.Scheduler;
|
import reactor.core.scheduler.Scheduler;
|
||||||
|
|
@ -20,7 +16,7 @@ public class ScrowAPI {
|
||||||
@Getter
|
@Getter
|
||||||
private static @Nullable MongoDatabase database;
|
private static @Nullable MongoDatabase database;
|
||||||
@Getter
|
@Getter
|
||||||
private static KenCommandApi<CommandSender, CommandContext<CommandSender>> commandManager;
|
private static BukkitKenCommandApi commandManager;
|
||||||
@Getter
|
@Getter
|
||||||
private static Scheduler minecraftScheduler;
|
private static Scheduler minecraftScheduler;
|
||||||
@Getter
|
@Getter
|
||||||
|
|
@ -39,7 +35,7 @@ public class ScrowAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
public static void setCommandManager(KenCommandApi<CommandSender, CommandContext<CommandSender>> commandManager) {
|
public static void setCommandManager(BukkitKenCommandApi commandManager) {
|
||||||
ScrowAPI.commandManager = commandManager;
|
ScrowAPI.commandManager = commandManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.email;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public interface Email extends EmailDraft {
|
|
||||||
|
|
||||||
Long getId();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return UUID of player the mail is sent to or null if console
|
|
||||||
*/
|
|
||||||
@Nullable UUID getFrom();
|
|
||||||
|
|
||||||
@Nullable Instant getSentAt();
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.email;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public interface EmailDraft {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return UUID of player sending the mail or null if console
|
|
||||||
*/
|
|
||||||
@Nullable UUID getFrom();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return non-empty string specifying the subject
|
|
||||||
*/
|
|
||||||
String getSubject();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return body of the message
|
|
||||||
*/
|
|
||||||
String getBody();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return id of the mail this mail is replying to or null if not replying to any email
|
|
||||||
*/
|
|
||||||
@Nullable Long getReplyTo();
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.email;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* like email but for minecraft
|
|
||||||
*/
|
|
||||||
public interface EmailService {
|
|
||||||
|
|
||||||
Mono<@NotNull Email> sendMail(UUID to, EmailDraft emailDraft);
|
|
||||||
Flux<@NotNull Email> sendMailToMany(Set<UUID> to, EmailDraft emailDraft);
|
|
||||||
|
|
||||||
Flux<@NotNull Email> fetchMails(UUID to);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param to uuid of player whose inbox to operate on
|
|
||||||
* @param id id of the email
|
|
||||||
*/
|
|
||||||
Mono<@NotNull Void> deleteMail(UUID to, long id);
|
|
||||||
}
|
|
||||||
|
|
@ -15,7 +15,7 @@ public interface FriendsService {
|
||||||
* @param other id of the player the initiator wants to end the friendship with
|
* @param other id of the player the initiator wants to end the friendship with
|
||||||
* @throws FriendRequestUsageException
|
* @throws FriendRequestUsageException
|
||||||
*/
|
*/
|
||||||
Mono<@NotNull Boolean> removeFriend(UUID initiator, UUID other);
|
Mono<@NotNull Boolean> removeFriend(Friendship friendship);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param playerId
|
* @param playerId
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,11 @@
|
||||||
package de.kentoj.scrow.bukkit.friends;
|
package de.kentoj.scrow.bukkit.friends;
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.util.pair.Tuple2;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public interface Friendship {
|
public interface Friendship {
|
||||||
Tuple2<UUID, UUID> getPlayerIds();
|
|
||||||
Instant getCreatedAt();
|
|
||||||
|
|
||||||
default UUID getOther(UUID self) {
|
OrderedUUIDPair getUuids();
|
||||||
final var ids = getPlayerIds();
|
|
||||||
return ids.getFirst() != self ? ids.getFirst() : ids.getSecond();
|
Instant getCreatedAt();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package de.kentoj.scrow.bukkit.friends;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class OrderedUUIDPair {
|
||||||
|
private final UUID first;
|
||||||
|
private final UUID second;
|
||||||
|
|
||||||
|
public OrderedUUIDPair(UUID uuid1, UUID uuid2) {
|
||||||
|
Preconditions.checkArgument(uuid1 != uuid2);
|
||||||
|
if (uuid1.compareTo(uuid2) < 0) {
|
||||||
|
this.first = uuid1;
|
||||||
|
this.second = uuid2;
|
||||||
|
} else {
|
||||||
|
this.first = uuid2;
|
||||||
|
this.second = uuid1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getOther(UUID self) {
|
||||||
|
final var ids = getFirst();
|
||||||
|
return getFirst().equals(self) ? getSecond() : getFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,7 +22,6 @@ dependencies {
|
||||||
implementation(project(":core-bukkit-api"))
|
implementation(project(":core-bukkit-api"))
|
||||||
|
|
||||||
implementation("org.spigotmc:spigot-api:1.21.11-R0.1-SNAPSHOT")
|
implementation("org.spigotmc:spigot-api:1.21.11-R0.1-SNAPSHOT")
|
||||||
implementation("de.kentoj:kencommandapi-bukkit:1.2.0")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package de.kentoj.scrow.bukkit;
|
package de.kentoj.scrow.bukkit;
|
||||||
|
|
||||||
import de.kentoj.kencommandapi.BukkitKenCommandApi;
|
|
||||||
import de.kentoj.scrow.bukkit.economy.CoinsCommand;
|
import de.kentoj.scrow.bukkit.economy.CoinsCommand;
|
||||||
import de.kentoj.scrow.bukkit.friends.command.FriendCommand;
|
import de.kentoj.scrow.bukkit.friends.command.FriendCommand;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
@ -15,9 +14,8 @@ public class CoreImplPlugin extends JavaPlugin {
|
||||||
ScrowAPISurface.initScrowAPI(this, false);
|
ScrowAPISurface.initScrowAPI(this, false);
|
||||||
|
|
||||||
{
|
{
|
||||||
BukkitKenCommandApi kenCommandApi = new BukkitKenCommandApi();
|
ScrowAPI.getCommandManager().register(new CoinsCommand().getRootNode());
|
||||||
ScrowAPI.getCommandManager().register(new CoinsCommand().create(), this);
|
ScrowAPI.getCommandManager().register(new FriendCommand().getRootNode());
|
||||||
ScrowAPI.getCommandManager().register(new FriendCommand().create(), this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,8 @@ import com.mongodb.MongoClientSettings;
|
||||||
import com.mongodb.reactivestreams.client.MongoClient;
|
import com.mongodb.reactivestreams.client.MongoClient;
|
||||||
import com.mongodb.reactivestreams.client.MongoClients;
|
import com.mongodb.reactivestreams.client.MongoClients;
|
||||||
import de.kentoj.kencommandapi.BukkitKenCommandApi;
|
import de.kentoj.kencommandapi.BukkitKenCommandApi;
|
||||||
import de.kentoj.scrow.bukkit.cmds2.CommandFactoryImpl;
|
|
||||||
import de.kentoj.scrow.bukkit.cmds2.bukkit.BukkitCommandManager;
|
|
||||||
import de.kentoj.scrow.bukkit.economy.InMemoryEconomyService;
|
import de.kentoj.scrow.bukkit.economy.InMemoryEconomyService;
|
||||||
import de.kentoj.scrow.bukkit.economy.MongoEconomyService;
|
import de.kentoj.scrow.bukkit.economy.MongoEconomyService;
|
||||||
import de.kentoj.scrow.bukkit.command.Commands;
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.bson.UuidRepresentation;
|
import org.bson.UuidRepresentation;
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,48 @@
|
||||||
package de.kentoj.scrow.bukkit.economy;
|
package de.kentoj.scrow.bukkit.economy;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.BukkitCommandContext;
|
||||||
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
import de.kentoj.kencommandapi.api.processing.CommandContext;
|
||||||
import de.kentoj.kencommandapi.api.structure.argument.CommandArgument;
|
import de.kentoj.kencommandapi.api.structure.argument.CommandArgument;
|
||||||
import de.kentoj.kencommandapi.api.structure.argument.types.IntegerArgumentType;
|
import de.kentoj.kencommandapi.api.structure.argument.types.IntegerArgumentType;
|
||||||
|
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
|
||||||
import de.kentoj.kencommandapi.type.OfflinePlayerArgumentType;
|
import de.kentoj.kencommandapi.type.OfflinePlayerArgumentType;
|
||||||
import de.kentoj.scrow.bukkit.ScrowAPI;
|
import de.kentoj.scrow.bukkit.ScrowAPI;
|
||||||
|
import lombok.Getter;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import reactor.core.scheduler.Schedulers;
|
import reactor.core.scheduler.Schedulers;
|
||||||
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
public class CoinsCommand {
|
public class CoinsCommand {
|
||||||
|
|
||||||
private final CommandArgument<CommandContext<CommandSender>, OfflinePlayer> playerArg;
|
@Getter
|
||||||
private final CommandArgument<CommandContext<CommandSender>, Integer> amountArg;
|
private final CommandNode<CommandSender, BukkitCommandContext> rootNode;
|
||||||
|
private final CommandArgument<CommandSender, BukkitCommandContext, OfflinePlayer> playerArg;
|
||||||
|
private final CommandArgument<CommandSender, BukkitCommandContext, Integer> amountArg;
|
||||||
|
|
||||||
public CoinsCommand() {
|
public CoinsCommand() {
|
||||||
var rootCommand = ScrowAPI.getCommandManager().createNode("coins");
|
this.rootNode = ScrowAPI.getCommandManager().createNode("coins");
|
||||||
this.playerArg = ScrowAPI.getCommandManager().createArgument("player", OfflinePlayerArgumentType.getInstance());
|
this.playerArg = ScrowAPI.getCommandManager().createArgument("player", OfflinePlayerArgumentType.getInstance());
|
||||||
this.amountArg = ScrowAPI.getCommandManager().createArgument("amount", IntegerArgumentType.getInstance());
|
this.amountArg = ScrowAPI.getCommandManager().createArgument("amount", new IntegerArgumentType<>());
|
||||||
|
|
||||||
{
|
{
|
||||||
var setLiteral = ScrowAPI.getCommandManager().createNode("set");
|
var setLiteral = ScrowAPI.getCommandManager().createNode("set");
|
||||||
rootCommand.addLiteral(setLiteral);
|
rootNode.addLiteral(setLiteral);
|
||||||
setLiteral.addArgument(playerArg);
|
setLiteral.addArgument(playerArg);
|
||||||
|
setLiteral.addArgument(amountArg);
|
||||||
setLiteral.setExecutor(this::setCoins);
|
setLiteral.setExecutor(this::setCoins);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var getLiteral = ScrowAPI.getCommandManager().createNode("get");
|
var getLiteral = ScrowAPI.getCommandManager().createNode("get");
|
||||||
rootCommand.addLiteral(getLiteral);
|
rootNode.addLiteral(getLiteral);
|
||||||
getLiteral.addArgument(playerArg);
|
getLiteral.addArgument(playerArg);
|
||||||
getLiteral.addArgument(amountArg);
|
|
||||||
getLiteral.setExecutor(this::getCoins);
|
getLiteral.setExecutor(this::getCoins);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getCoins(CommandContext<CommandSender> ctx) {
|
private void getCoins(BukkitCommandContext ctx) {
|
||||||
var player = ctx.getArg(playerArg);
|
var player = ctx.getArg(playerArg);
|
||||||
|
|
||||||
ScrowAPI.getEconomyService()
|
ScrowAPI.getEconomyService()
|
||||||
|
|
@ -57,7 +61,7 @@ public class CoinsCommand {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCoins(CommandContext<CommandSender> ctx) {
|
private void setCoins(BukkitCommandContext ctx) {
|
||||||
var player = ctx.getArg(playerArg);
|
var player = ctx.getArg(playerArg);
|
||||||
var amount = ctx.getArg(amountArg);
|
var amount = ctx.getArg(amountArg);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
package de.kentoj.scrow.bukkit.friends.command;
|
package de.kentoj.scrow.bukkit.friends.command;
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.command.Commands;
|
import de.kentoj.kencommandapi.BukkitCommandContext;
|
||||||
import de.kentoj.scrow.bukkit.command.literal.RootLiteral;
|
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
|
||||||
|
import de.kentoj.scrow.bukkit.ScrowAPI;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
public class FriendCommand {
|
public class FriendCommand {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final CommandNode<CommandSender, BukkitCommandContext> rootNode;
|
||||||
|
|
||||||
public FriendCommand() {
|
public FriendCommand() {
|
||||||
rootLiteral = Commands.root("friend");
|
this.rootNode = ScrowAPI.getCommandManager().createNode("friends", "f", "friend");
|
||||||
rootLiteral.addAliases("f", "friends");
|
rootNode.addLiteral(new FriendListLiteral().getNode());
|
||||||
|
|
||||||
rootLiteral.addLiteral(new FriendListLiteral().create());
|
|
||||||
}
|
|
||||||
|
|
||||||
public RootLiteral create() {
|
|
||||||
return rootLiteral;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,48 +1,37 @@
|
||||||
package de.kentoj.scrow.bukkit.friends.command;
|
package de.kentoj.scrow.bukkit.friends.command;
|
||||||
|
|
||||||
|
import de.kentoj.kencommandapi.BukkitCommandContext;
|
||||||
|
import de.kentoj.kencommandapi.api.structure.node.CommandNode;
|
||||||
import de.kentoj.scrow.bukkit.ScrowAPI;
|
import de.kentoj.scrow.bukkit.ScrowAPI;
|
||||||
import de.kentoj.scrow.bukkit.command.Commands;
|
import lombok.Getter;
|
||||||
import de.kentoj.scrow.bukkit.command.execution.CommandContext;
|
|
||||||
import de.kentoj.scrow.bukkit.command.literal.Literal;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.command.CommandSender;
|
||||||
import reactor.core.scheduler.Schedulers;
|
import reactor.core.scheduler.Schedulers;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class FriendListLiteral {
|
public class FriendListLiteral {
|
||||||
|
|
||||||
private final Literal literal;
|
@Getter
|
||||||
|
private final CommandNode<CommandSender, BukkitCommandContext> node;
|
||||||
|
|
||||||
public FriendListLiteral() {
|
public FriendListLiteral() {
|
||||||
literal = Commands.literal("list");
|
this.node = ScrowAPI.getCommandManager().createNode("list");
|
||||||
literal.setExecutor(this::listFriends);
|
node.setExecutor(this::friendList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Literal create() {
|
private void friendList(BukkitCommandContext ctx) {
|
||||||
return literal;
|
var ownUid = ctx.getPlayerSender().getUniqueId();
|
||||||
}
|
ctx.getPlayerSender().sendMessage("friends:");
|
||||||
|
ScrowAPI.getFriendsService().getFriendships(ownUid)
|
||||||
private void listFriends(CommandContext ctx) {
|
|
||||||
ScrowAPI.getFriendsService().getFriendships(ctx.getSenderPlayer().getUniqueId())
|
|
||||||
.subscribeOn(Schedulers.boundedElastic())
|
|
||||||
.collectList()
|
|
||||||
.publishOn(ScrowAPI.getMinecraftScheduler())
|
.publishOn(ScrowAPI.getMinecraftScheduler())
|
||||||
.subscribe(friendships -> {
|
.subscribeOn(Schedulers.boundedElastic())
|
||||||
if (friendships.isEmpty()) {
|
.map(friendship -> {
|
||||||
ctx.getSender().sendMessage("You have no friends.");
|
var friendPlayerUid = friendship.getOther(ownUid);
|
||||||
} else {
|
var friendPlayerName = Bukkit.getOfflinePlayer(friendPlayerUid).getName();
|
||||||
ctx.getSender().sendMessage("You have " + friendships.size() + " friends:");
|
return "- " + friendPlayerName;
|
||||||
friendships.forEach(friendship -> {
|
}).doOnNext(line -> {
|
||||||
final UUID friendId = friendship.getOther(ctx.getSenderPlayer().getUniqueId());
|
ctx.getPlayerSender().sendMessage(line);
|
||||||
// TODO get name even if never online on the network
|
}).doOnComplete(() -> {
|
||||||
final OfflinePlayer friend = Bukkit.getOfflinePlayer(friendId);
|
ctx.getPlayerSender().sendMessage("EOF");
|
||||||
ctx.getSender().sendMessage("- " + friend.getName());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, error -> {
|
|
||||||
ctx.getSender().sendMessage("Error fetching friends");
|
|
||||||
// TODO improve handling
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.friends.friendship;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import de.kentoj.scrow.bukkit.friends.Friendship;
|
|
||||||
import de.kentoj.scrow.bukkit.util.pair.Tuple2;
|
|
||||||
import lombok.Value;
|
|
||||||
import org.bson.codecs.pojo.annotations.BsonCreator;
|
|
||||||
import org.bson.codecs.pojo.annotations.BsonProperty;
|
|
||||||
import org.bson.types.ObjectId;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
|
|
||||||
@Value
|
|
||||||
public class BsonFriendship implements Friendship {
|
|
||||||
ObjectId id;
|
|
||||||
Tuple2<UUID, UUID> playerIds;
|
|
||||||
Instant createdAt;
|
|
||||||
|
|
||||||
@BsonCreator
|
|
||||||
public BsonFriendship(
|
|
||||||
@BsonProperty("_id") ObjectId id,
|
|
||||||
@BsonProperty("playerIds") Tuple2<UUID, UUID> playerIds,
|
|
||||||
@BsonProperty("createdAt") Instant createdAt
|
|
||||||
) {
|
|
||||||
Preconditions.checkArgument(playerIds.getFirst() != playerIds.getSecond());
|
|
||||||
this.id = id;
|
|
||||||
this.playerIds = FriendshipUtils.toOrderedTuple(playerIds);
|
|
||||||
this.createdAt = createdAt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BsonFriendship(Tuple2<UUID, UUID> playerIds, Instant createdAt) {
|
|
||||||
this(ObjectId.get(), playerIds, createdAt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package de.kentoj.scrow.bukkit.friends.friendship;
|
||||||
|
|
||||||
|
import de.kentoj.scrow.bukkit.friends.Friendship;
|
||||||
|
import de.kentoj.scrow.bukkit.friends.OrderedUUIDPair;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Value
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class FriendshipImpl implements Friendship {
|
||||||
|
OrderedUUIDPair uuids;
|
||||||
|
Instant createdAt;
|
||||||
|
|
||||||
|
public FriendshipImpl(UUID uuid1, UUID uuid2, Instant createdAt) {
|
||||||
|
this(new OrderedUUIDPair(uuid1, uuid2), createdAt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,15 +13,13 @@ public interface FriendshipRepository {
|
||||||
|
|
||||||
Flux<@NotNull Friendship> getFriendships(UUID playerId);
|
Flux<@NotNull Friendship> getFriendships(UUID playerId);
|
||||||
|
|
||||||
Mono<@NotNull Friendship> getFriendship(Tuple2<UUID, UUID> playerIds);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return True if friendship saved, false if friendship already exists
|
* @return True if friendship saved, false if friendship already exists
|
||||||
*/
|
*/
|
||||||
Mono<@NotNull Boolean> saveFriendship(Tuple2<UUID, UUID> playerIds, Instant createdAt);
|
Mono<@NotNull Boolean> saveFriendship(Friendship playerIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return True if friendship deleted, false if none found
|
* @return True if friendship deleted, false if none found
|
||||||
*/
|
*/
|
||||||
Mono<@NotNull Boolean> deleteFriendship(Tuple2<UUID, UUID> playerIds);
|
Mono<@NotNull Boolean> deleteFriendship(UUID uuid1, UUID uuid2);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
package de.kentoj.scrow.bukkit.friends.friendship;
|
|
||||||
|
|
||||||
import de.kentoj.scrow.bukkit.util.pair.Tuple2;
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
|
||||||
class FriendshipUtils {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ensures constant order
|
|
||||||
* @return an ordered tuple
|
|
||||||
*/
|
|
||||||
public static Tuple2<UUID, UUID> toOrderedTuple(Tuple2<UUID, UUID> playerIds) {
|
|
||||||
if (playerIds.getFirst().compareTo(playerIds.getSecond()) < 0)
|
|
||||||
return new Tuple2<>(playerIds.getFirst(), playerIds.getSecond());
|
|
||||||
else
|
|
||||||
return new Tuple2<>(playerIds.getSecond(), playerIds.getFirst());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -8,12 +8,13 @@ import com.mongodb.client.model.Indexes;
|
||||||
import com.mongodb.reactivestreams.client.MongoCollection;
|
import com.mongodb.reactivestreams.client.MongoCollection;
|
||||||
import com.mongodb.reactivestreams.client.MongoDatabase;
|
import com.mongodb.reactivestreams.client.MongoDatabase;
|
||||||
import de.kentoj.scrow.bukkit.friends.Friendship;
|
import de.kentoj.scrow.bukkit.friends.Friendship;
|
||||||
import de.kentoj.scrow.bukkit.util.pair.Tuple2;
|
import de.kentoj.scrow.bukkit.friends.OrderedUUIDPair;
|
||||||
|
import org.bson.Document;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.sql.Date;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class MongoFriendshipRepository implements FriendshipRepository {
|
public class MongoFriendshipRepository implements FriendshipRepository {
|
||||||
|
|
@ -28,8 +29,8 @@ public class MongoFriendshipRepository implements FriendshipRepository {
|
||||||
database.createCollection(COLLECTION_NAME);
|
database.createCollection(COLLECTION_NAME);
|
||||||
collection().createIndex(
|
collection().createIndex(
|
||||||
Indexes.compoundIndex(
|
Indexes.compoundIndex(
|
||||||
Indexes.ascending("playerIds.first"),
|
Indexes.ascending("first"),
|
||||||
Indexes.ascending("playerIds.second")
|
Indexes.ascending("second")
|
||||||
),
|
),
|
||||||
new IndexOptions().unique(true)
|
new IndexOptions().unique(true)
|
||||||
);
|
);
|
||||||
|
|
@ -39,48 +40,50 @@ public class MongoFriendshipRepository implements FriendshipRepository {
|
||||||
public Flux<@NotNull Friendship> getFriendships(UUID playerId) {
|
public Flux<@NotNull Friendship> getFriendships(UUID playerId) {
|
||||||
return Flux.from(collection()
|
return Flux.from(collection()
|
||||||
.find(Filters.or(
|
.find(Filters.or(
|
||||||
Filters.eq("playerIds.first", playerId),
|
Filters.eq("first", playerId),
|
||||||
Filters.eq("playerIds.second", playerId)
|
Filters.eq("second", playerId)
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<@NotNull Friendship> getFriendship(Tuple2<UUID, UUID> playerIds) {
|
|
||||||
playerIds = FriendshipUtils.toOrderedTuple(playerIds);
|
|
||||||
return Mono.from(collection()
|
|
||||||
.find(Filters.and(
|
|
||||||
Filters.eq("playerIds.first", playerIds.getFirst()),
|
|
||||||
Filters.eq("playerIds.second", playerIds.getSecond())
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<@NotNull Boolean> saveFriendship(Tuple2<UUID, UUID> playerIds, Instant createdAt) {
|
|
||||||
var friendship = new BsonFriendship(playerIds, createdAt);
|
|
||||||
return Mono.from(collection()
|
|
||||||
.insertOne(friendship)
|
|
||||||
)
|
|
||||||
.map(__ -> true)
|
|
||||||
.onErrorResume(e -> {
|
|
||||||
if (!(e instanceof MongoWriteException)) return Mono.error(e);
|
|
||||||
if (((MongoWriteException) e).getError().getCategory() != ErrorCategory.DUPLICATE_KEY)
|
|
||||||
return Mono.error(e);
|
|
||||||
return Mono.just(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<@NotNull Boolean> deleteFriendship(Tuple2<UUID, UUID> playerIds) {
|
|
||||||
playerIds = FriendshipUtils.toOrderedTuple(playerIds);
|
|
||||||
return Mono.from(collection()
|
|
||||||
.deleteOne(Filters.and(
|
|
||||||
Filters.eq("playerIds.first", playerIds.getFirst()),
|
|
||||||
Filters.eq("playerIds.second", playerIds.getSecond())
|
|
||||||
)))
|
)))
|
||||||
|
.map(this::fromDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<@NotNull Boolean> saveFriendship(Friendship friendship) {
|
||||||
|
return Mono.from(collection()
|
||||||
|
.insertOne(toDocument(friendship)))
|
||||||
|
.thenReturn(true)
|
||||||
|
.onErrorResume(MongoWriteException.class, e ->
|
||||||
|
e.getError().getCategory() == ErrorCategory.DUPLICATE_KEY
|
||||||
|
? Mono.just(Boolean.FALSE)
|
||||||
|
: Mono.error(e)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<@NotNull Boolean> deleteFriendship(UUID uuid1, UUID uuid2) {
|
||||||
|
var uuids = new OrderedUUIDPair(uuid1, uuid2);
|
||||||
|
return Mono.from(collection()
|
||||||
|
.deleteOne(Filters.and(
|
||||||
|
Filters.eq("first", uuids.getFirst()),
|
||||||
|
Filters.eq("second", uuids.getSecond())
|
||||||
|
)))
|
||||||
.map(res -> res.getDeletedCount() > 0);
|
.map(res -> res.getDeletedCount() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MongoCollection<BsonFriendship> collection() {
|
private MongoCollection<Document> collection() {
|
||||||
return database.getCollection(COLLECTION_NAME, BsonFriendship.class);
|
return database.getCollection(COLLECTION_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
private @NotNull Friendship fromDocument(Document doc) {
|
||||||
|
var first = UUID.fromString(doc.getString("first"));
|
||||||
|
var second = UUID.fromString(doc.getString("second"));
|
||||||
|
var createdAt = doc.getDate("createdAt").toInstant();
|
||||||
|
return new FriendshipImpl(first, second, createdAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
private @NotNull Document toDocument(Friendship friendship) {
|
||||||
|
return new Document()
|
||||||
|
.append("first", friendship.getUuids().getFirst().toString())
|
||||||
|
.append("second", friendship.getUuids().getSecond().toString())
|
||||||
|
.append("createdAt", Date.from(friendship.getCreatedAt()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue