Compare commits

..

9 Commits

66 changed files with 1480 additions and 813 deletions

View File

@ -2,6 +2,7 @@ name: Announce release on discord
on: on:
release: release:
types: [published] types: [published]
jobs: jobs:
send_announcement: send_announcement:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -11,7 +12,7 @@ jobs:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
DISCORD_USERNAME: PlotSquared Release DISCORD_USERNAME: PlotSquared Release
DISCORD_AVATAR: https://raw.githubusercontent.com/IntellectualSites/Assets/main/plugins/PlotSquared/PlotSquared.png DISCORD_AVATAR: https://raw.githubusercontent.com/IntellectualSites/Assets/main/plugins/PlotSquared/PlotSquared.png
uses: Ilshidur/action-discord@0c4b27844ba47cb1c7bee539c8eead5284ce9fa9 # ratchet:Ilshidur/action-discord@0.3.2 uses: Ilshidur/action-discord@0.3.2
with: with:
args: | args: |
"<@&525015541815967744> <@&679322738552471574> <@&699293353862496266>" "<@&525015541815967744> <@&679322738552471574> <@&699293353862496266>"

View File

@ -1,17 +1,19 @@
name: Build PR name: Build PR
on: [pull_request]
on: [ pull_request ]
jobs: jobs:
build_pr: build_pr:
if: github.repository_owner == 'IntellectualSites' if: github.repository_owner == 'IntellectualSites'
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest] os: [ ubuntu-latest, windows-latest, macos-latest ]
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Validate Gradle Wrapper - name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@55e685c48d84285a5b0418cd094606e199cca3b6 # v1 uses: gradle/wrapper-validation-action@v1
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v3 uses: actions/setup-java@v3
with: with:

View File

@ -1,8 +1,10 @@
name: build name: build
on: on:
push: push:
branches: branches:
- v7 - v7
jobs: jobs:
build: build:
if: github.repository_owner == 'IntellectualSites' if: github.repository_owner == 'IntellectualSites'
@ -11,7 +13,7 @@ jobs:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Validate Gradle Wrapper - name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@55e685c48d84285a5b0418cd094606e199cca3b6 # v1 uses: gradle/wrapper-validation-action@v1
- name: Setup Java - name: Setup Java
uses: actions/setup-java@v3 uses: actions/setup-java@v3
with: with:
@ -42,14 +44,9 @@ jobs:
ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }} ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }}
ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }} ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
- name: Publish core javadoc - name: Publish core javadoc
<<<<<<< HEAD
# if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/v7'}} # if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/v7'}}
if: ${{ runner.os == 'Linux' && env.STATUS == 'snapshot' && github.event_name == 'push' && github.ref == 'refs/heads/v7'}} if: ${{ runner.os == 'Linux' && env.STATUS == 'snapshot' && github.event_name == 'push' && github.ref == 'refs/heads/v7'}}
uses: cpina/github-action-push-to-another-repository@main uses: cpina/github-action-push-to-another-repository@main
=======
if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/v6'}}
uses: cpina/github-action-push-to-another-repository@0a14457bb28b04dfa1652e0ffdfda866d2845c73 # main
>>>>>>> v6
env: env:
SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }} SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }}
with: with:
@ -62,7 +59,7 @@ jobs:
- name: Publish bukkit javadoc - name: Publish bukkit javadoc
# if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/v7'}} # if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/v7'}}
if: ${{ runner.os == 'Linux' && env.STATUS == 'snapshot' && github.event_name == 'push' && github.ref == 'refs/heads/v7'}} if: ${{ runner.os == 'Linux' && env.STATUS == 'snapshot' && github.event_name == 'push' && github.ref == 'refs/heads/v7'}}
uses: cpina/github-action-push-to-another-repository@0a14457bb28b04dfa1652e0ffdfda866d2845c73 # main uses: cpina/github-action-push-to-another-repository@main
env: env:
SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }} SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }}
with: with:

View File

@ -1,4 +1,5 @@
name: "CodeQL" name: "CodeQL"
on: on:
push: push:
branches: [ v7 ] branches: [ v7 ]
@ -14,18 +15,23 @@ jobs:
actions: read actions: read
contents: read contents: read
security-events: write security-events: write
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
language: ['java'] language: [ 'java' ]
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@32dc499307d133bb5085bae78498c0ac2cf762d5 # v2 uses: github/codeql-action/init@v2
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@32dc499307d133bb5085bae78498c0ac2cf762d5 # v2 uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@32dc499307d133bb5085bae78498c0ac2cf762d5 # v2 uses: github/codeql-action/analyze@v2

View File

@ -1,12 +1,14 @@
name: draft release name: draft release
on: on:
push: push:
branches: branches:
- v6 - v6
pull_request: pull_request:
types: [opened, reopened, synchronize] types: [ opened, reopened, synchronize ]
pull_request_target: pull_request_target:
types: [opened, reopened, synchronize] types: [ opened, reopened, synchronize ]
jobs: jobs:
update_release_draft: update_release_draft:
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}

View File

@ -53,6 +53,10 @@ dependencies {
// Adventure // Adventure
implementation("net.kyori:adventure-platform-bukkit") implementation("net.kyori:adventure-platform-bukkit")
// Cloud
implementation(libs.cloudPaper)
implementation(libs.cloudMinecraftExtras)
} }
tasks.processResources { tasks.processResources {

View File

@ -63,6 +63,7 @@ import com.plotsquared.bukkit.uuid.SquirrelIdUUIDService;
import com.plotsquared.core.PlotPlatform; import com.plotsquared.core.PlotPlatform;
import com.plotsquared.core.PlotSquared; import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.backup.BackupManager; import com.plotsquared.core.backup.BackupManager;
import com.plotsquared.core.commands.PlotSquaredCommandManager;
import com.plotsquared.core.components.ComponentPresetManager; import com.plotsquared.core.components.ComponentPresetManager;
import com.plotsquared.core.configuration.ConfigurationNode; import com.plotsquared.core.configuration.ConfigurationNode;
import com.plotsquared.core.configuration.ConfigurationSection; import com.plotsquared.core.configuration.ConfigurationSection;
@ -215,6 +216,8 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl
@Inject @Inject
private PlatformWorldManager<World> worldManager; private PlatformWorldManager<World> worldManager;
private Locale serverLocale; private Locale serverLocale;
@Inject
private PlotSquaredCommandManager commandManager;
@SuppressWarnings("StringSplitter") @SuppressWarnings("StringSplitter")
@Override @Override
@ -382,6 +385,7 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl
// Commands // Commands
if (Settings.Enabled_Components.COMMANDS) { if (Settings.Enabled_Components.COMMANDS) {
this.registerCommands(); this.registerCommands();
this.commandManager.initializeCommands();
} }
// Permissions // Permissions

View File

@ -18,12 +18,16 @@
*/ */
package com.plotsquared.bukkit.inject; package com.plotsquared.bukkit.inject;
import cloud.commandframework.CommandManager;
import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator;
import cloud.commandframework.paper.PaperCommandManager;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.assistedinject.FactoryModuleBuilder;
import com.plotsquared.bukkit.BukkitPlatform; import com.plotsquared.bukkit.BukkitPlatform;
import com.plotsquared.bukkit.listener.SingleWorldListener; import com.plotsquared.bukkit.listener.SingleWorldListener;
import com.plotsquared.bukkit.player.BukkitPlayer;
import com.plotsquared.bukkit.player.BukkitPlayerManager; import com.plotsquared.bukkit.player.BukkitPlayerManager;
import com.plotsquared.bukkit.queue.BukkitChunkCoordinator; import com.plotsquared.bukkit.queue.BukkitChunkCoordinator;
import com.plotsquared.bukkit.queue.BukkitQueueCoordinator; import com.plotsquared.bukkit.queue.BukkitQueueCoordinator;
@ -47,6 +51,8 @@ import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory;
import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory; import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory;
import com.plotsquared.core.inject.factory.HybridPlotWorldFactory; import com.plotsquared.core.inject.factory.HybridPlotWorldFactory;
import com.plotsquared.core.inject.factory.ProgressSubscriberFactory; import com.plotsquared.core.inject.factory.ProgressSubscriberFactory;
import com.plotsquared.core.player.ConsolePlayer;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.world.DefaultPlotAreaManager; import com.plotsquared.core.plot.world.DefaultPlotAreaManager;
import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.plot.world.SinglePlotAreaManager; import com.plotsquared.core.plot.world.SinglePlotAreaManager;
@ -68,10 +74,14 @@ import com.sk89q.worldedit.extension.platform.Actor;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.function.Function;
public class BukkitModule extends AbstractModule { public class BukkitModule extends AbstractModule {
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + BukkitModule.class.getSimpleName()); private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + BukkitModule.class.getSimpleName());
@ -145,4 +155,27 @@ public class BukkitModule extends AbstractModule {
return EconHandler.nullEconHandler(); return EconHandler.nullEconHandler();
} }
@Provides
@Singleton
@NonNull CommandManager<PlotPlayer<?>> provideCommandManager() throws Exception {
final Function<PlotPlayer<?>, CommandSender> plotToPlatform = plotPlayer -> {
if (plotPlayer instanceof BukkitPlayer bukkitPlayer) {
return bukkitPlayer.getPlatformPlayer();
}
return Bukkit.getConsoleSender();
};
final Function<CommandSender, PlotPlayer<?>> platformToPlot = commandSender -> {
if (commandSender instanceof Player player) {
return BukkitUtil.adapt(player);
}
return ConsolePlayer.getConsole();
};
return new PaperCommandManager<>(
this.bukkitPlatform,
AsynchronousCommandExecutionCoordinator.<PlotPlayer<?>>builder().withSynchronousParsing().build(),
platformToPlot,
plotToPlatform
);
}
} }

View File

@ -52,7 +52,7 @@ public class MVdWPlaceholders {
@Subscribe @Subscribe
public void onNewPlaceholder(final PlaceholderRegistry.@NonNull PlaceholderAddedEvent event) { public void onNewPlaceholder(final PlaceholderRegistry.@NonNull PlaceholderAddedEvent event) {
this.addPlaceholder(event.placeholder()); this.addPlaceholder(event.getPlaceholder());
} }
private void addPlaceholder(final @NonNull Placeholder placeholder) { private void addPlaceholder(final @NonNull Placeholder placeholder) {

View File

@ -110,9 +110,9 @@ public class GenChunk extends ZeroedDelegateScopedQueueCoordinator {
*/ */
public void setChunk(@NonNull ChunkWrapper wrap) { public void setChunk(@NonNull ChunkWrapper wrap) {
chunk = null; chunk = null;
world = wrap.world(); world = wrap.world;
chunkX = wrap.x(); chunkX = wrap.x;
chunkZ = wrap.z(); chunkZ = wrap.z;
} }
@Override @Override

View File

@ -124,7 +124,7 @@ public class BukkitSetupUtils extends SetupUtils {
public String setupWorld(PlotAreaBuilder builder) { public String setupWorld(PlotAreaBuilder builder) {
this.updateGenerators(false); this.updateGenerators(false);
ConfigurationNode[] steps = builder.settingsNodesWrapper() == null ? ConfigurationNode[] steps = builder.settingsNodesWrapper() == null ?
new ConfigurationNode[0] : builder.settingsNodesWrapper().settingsNodes(); new ConfigurationNode[0] : builder.settingsNodesWrapper().getSettingsNodes();
String world = builder.worldName(); String world = builder.worldName();
PlotAreaType type = builder.plotAreaType(); PlotAreaType type = builder.plotAreaType();
String worldPath = "worlds." + builder.worldName(); String worldPath = "worlds." + builder.worldName();

View File

@ -111,8 +111,8 @@ public class SQLiteUUIDService implements UUIDService, Consumer<List<UUIDMapping
try (final PreparedStatement statement = getConnection() try (final PreparedStatement statement = getConnection()
.prepareStatement("INSERT OR REPLACE INTO `usercache` (`uuid`, `username`) VALUES(?, ?)")) { .prepareStatement("INSERT OR REPLACE INTO `usercache` (`uuid`, `username`) VALUES(?, ?)")) {
for (final UUIDMapping mapping : uuidWrappers) { for (final UUIDMapping mapping : uuidWrappers) {
statement.setString(1, mapping.uuid().toString()); statement.setString(1, mapping.getUuid().toString());
statement.setString(2, mapping.username()); statement.setString(2, mapping.getUsername());
statement.executeUpdate(); statement.executeUpdate();
} }
} catch (SQLException e) { } catch (SQLException e) {

View File

@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
## Enforcement ## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at contact<at>intellectualsites.com. All reported by contacting the project team at contact@intellectualsites.com. All
complaints will be reviewed and investigated and will result in a response that complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident. obligated to maintain confidentiality with regard to the reporter of an incident.

View File

@ -15,6 +15,11 @@ dependencies {
api("net.kyori:adventure-api") api("net.kyori:adventure-api")
api("net.kyori:adventure-text-minimessage") api("net.kyori:adventure-text-minimessage")
// Cloud
api(libs.cloudServices)
api(libs.cloudCore)
api(libs.cloudAnnotations)
// Guice // Guice
api(libs.guice) { api(libs.guice) {
exclude(group = "com.google.guava") exclude(group = "com.google.guava")
@ -40,7 +45,6 @@ dependencies {
// Other libraries // Other libraries
api(libs.prtree) api(libs.prtree)
api(libs.aopalliance) api(libs.aopalliance)
api(libs.cloudServices)
api(libs.arkitektonika) api(libs.arkitektonika)
api("com.intellectualsites.paster:Paster") api("com.intellectualsites.paster:Paster")
api("com.intellectualsites.informative-annotations:informative-annotations") api("com.intellectualsites.informative-annotations:informative-annotations")

View File

@ -136,29 +136,33 @@ public class SimpleBackupManager implements BackupManager {
return this.backupLimit; return this.backupLimit;
} }
private record PlotCacheKey( private static final class PlotCacheKey {
Plot plot
) {
@Override private final Plot plot;
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final PlotCacheKey that = (PlotCacheKey) o;
return Objects.equals(plot.getArea(), that.plot.getArea())
&& Objects.equals(plot.getId(), that.plot.getId())
&& Objects.equals(plot.getOwnerAbs(), that.plot.getOwnerAbs());
}
@Override
public int hashCode() {
return Objects.hash(plot.getArea(), plot.getId(), plot.getOwnerAbs());
}
private PlotCacheKey(Plot plot) {
this.plot = plot;
} }
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final PlotCacheKey that = (PlotCacheKey) o;
return Objects.equals(plot.getArea(), that.plot.getArea())
&& Objects.equals(plot.getId(), that.plot.getId())
&& Objects.equals(plot.getOwnerAbs(), that.plot.getOwnerAbs());
}
@Override
public int hashCode() {
return Objects.hash(plot.getArea(), plot.getId(), plot.getOwnerAbs());
}
}
} }

View File

@ -1,172 +0,0 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.command;
import com.google.inject.Inject;
import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.database.DBFunc;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.util.EventDispatcher;
import com.plotsquared.core.util.PlayerManager;
import com.plotsquared.core.util.TabCompletions;
import com.plotsquared.core.util.task.RunnableVal2;
import com.plotsquared.core.util.task.RunnableVal3;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeoutException;
@CommandDeclaration(command = "add",
usage = "/plot add <player | *>",
category = CommandCategory.SETTINGS,
permission = "plots.add",
requiredType = RequiredType.PLAYER)
public class Add extends Command {
private final EventDispatcher eventDispatcher;
@Inject
public Add(final @NonNull EventDispatcher eventDispatcher) {
super(MainCommand.getInstance(), true);
this.eventDispatcher = eventDispatcher;
}
@Override
public CompletableFuture<Boolean> execute(
final PlotPlayer<?> player,
String[] args,
RunnableVal3<Command, Runnable, Runnable> confirm,
RunnableVal2<Command, CommandResult> whenDone
) throws CommandException {
final Plot plot = check(player.getCurrentPlot(), TranslatableCaption.of("errors.not_in_plot"));
checkTrue(plot.hasOwner(), TranslatableCaption.of("info.plot_unowned"));
checkTrue(
plot.isOwner(player.getUUID()) || player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_TRUST),
TranslatableCaption.of("permission.no_plot_perms")
);
checkTrue(args.length == 1,
TranslatableCaption.of("commandconfig.command_syntax"),
TagResolver.resolver("value", Tag.inserting(Component.text("/plot add <player | *>")))
);
final CompletableFuture<Boolean> future = new CompletableFuture<>();
PlayerManager.getUUIDsFromString(args[0], (uuids, throwable) -> {
if (throwable != null) {
if (throwable instanceof TimeoutException) {
player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout"));
} else {
player.sendMessage(
TranslatableCaption.of("errors.invalid_player"),
TagResolver.resolver("value", Tag.inserting(Component.text(args[0])))
);
}
future.completeExceptionally(throwable);
return;
} else {
try {
checkTrue(!uuids.isEmpty(), TranslatableCaption.of("errors.invalid_player"),
TagResolver.resolver("value", Tag.inserting(Component.text(args[0])))
);
Iterator<UUID> iterator = uuids.iterator();
int size = plot.getTrusted().size() + plot.getMembers().size();
while (iterator.hasNext()) {
UUID uuid = iterator.next();
if (uuid == DBFunc.EVERYONE && !(player.hasPermission(Permission.PERMISSION_TRUST_EVERYONE) || player.hasPermission(
Permission.PERMISSION_ADMIN_COMMAND_TRUST))) {
player.sendMessage(
TranslatableCaption.of("errors.invalid_player"),
TagResolver.resolver("value", Tag.inserting(
PlayerManager.resolveName(uuid).toComponent(player)
))
);
iterator.remove();
continue;
}
if (plot.isOwner(uuid)) {
player.sendMessage(
TranslatableCaption.of("member.already_added"),
TagResolver.resolver("player", Tag.inserting(
PlayerManager.resolveName(uuid).toComponent(player)
))
);
iterator.remove();
continue;
}
if (plot.getMembers().contains(uuid)) {
player.sendMessage(
TranslatableCaption.of("member.already_added"),
TagResolver.resolver("player", Tag.inserting(
PlayerManager.resolveName(uuid).toComponent(player)
))
);
iterator.remove();
continue;
}
size += plot.getTrusted().contains(uuid) ? 0 : 1;
}
checkTrue(!uuids.isEmpty(), null);
int localAddSize = plot.getMembers().size();
int maxAddSize = player.hasPermissionRange(Permission.PERMISSION_ADD, Settings.Limit.MAX_PLOTS);
if (localAddSize >= maxAddSize) {
player.sendMessage(
TranslatableCaption.of("members.plot_max_members_added"),
TagResolver.resolver("amount", Tag.inserting(Component.text(localAddSize)))
);
return;
}
// Success
confirm.run(this, () -> {
for (UUID uuid : uuids) {
if (uuid != DBFunc.EVERYONE) {
if (!plot.removeTrusted(uuid)) {
if (plot.getDenied().contains(uuid)) {
plot.removeDenied(uuid);
}
}
}
plot.addMember(uuid);
this.eventDispatcher.callMember(player, plot, uuid, true);
player.sendMessage(TranslatableCaption.of("member.member_added"));
}
}, null);
} catch (final Throwable exception) {
future.completeExceptionally(exception);
return;
}
}
future.complete(true);
});
return future;
}
@Override
public Collection<Command> tab(final PlotPlayer<?> player, final String[] args, final boolean space) {
return TabCompletions.completePlayers(player, String.join(",", args).trim(), Collections.emptyList());
}
}

View File

@ -1,210 +0,0 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.command;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.query.PlotQuery;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeoutException;
@CommandDeclaration(command = "alias",
permission = "plots.alias",
usage = "/plot alias <set | remove> <alias>",
aliases = {"setalias", "sa", "name", "rename", "setname", "seta", "nameplot"},
category = CommandCategory.SETTINGS,
requiredType = RequiredType.PLAYER)
public class Alias extends SubCommand {
private static final Command SET_COMMAND = new Command(null, false, "set", null, RequiredType.NONE, null) {
};
private static final Command REMOVE_COMMAND = new Command(null, false, "remove", null, RequiredType.NONE, null) {
};
@Override
public boolean onCommand(PlotPlayer<?> player, String[] args) {
if (args.length == 0) {
sendUsage(player);
return false;
}
Location location = player.getLocation();
Plot plot = location.getPlotAbs();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return false;
}
if (!plot.hasOwner()) {
player.sendMessage(TranslatableCaption.of("working.plot_not_claimed"));
return false;
}
boolean result = false;
boolean owner = plot.isOwner(player.getUUID());
boolean permission;
boolean admin;
switch (args[0].toLowerCase()) {
case "set" -> {
if (args.length != 2) {
sendUsage(player);
return false;
}
permission = isPermitted(player, Permission.PERMISSION_ALIAS_SET);
admin = isPermitted(player, Permission.PERMISSION_ADMIN_ALIAS_SET);
if (!admin && !owner) {
player.sendMessage(TranslatableCaption.of("permission.no_plot_perms"));
return false;
}
if (permission) { // is either admin or owner
setAlias(player, plot, args[1]);
return true;
} else {
player.sendMessage(
TranslatableCaption.of("permission.no_permission"),
TagResolver.resolver(
"node",
Tag.inserting(Permission.PERMISSION_ALIAS_SET)
)
);
}
}
case "remove" -> {
permission = isPermitted(player, Permission.PERMISSION_ALIAS_REMOVE);
admin = isPermitted(player, Permission.PERMISSION_ADMIN_ALIAS_REMOVE);
if (!admin && !owner) {
player.sendMessage(TranslatableCaption.of("permission.no_plot_perms"));
return false;
}
if (permission) {
result = removeAlias(player, plot);
} else {
player.sendMessage(
TranslatableCaption.of("permission.no_permission"),
TagResolver.resolver(
"node",
Tag.inserting(Permission.PERMISSION_ALIAS_REMOVE)
)
);
}
}
default -> {
sendUsage(player);
result = false;
}
}
return result;
}
@Override
public Collection<Command> tab(PlotPlayer<?> player, String[] args, boolean space) {
final List<Command> commands = new ArrayList<>(2);
if (args.length == 1) {
if ("set".startsWith(args[0])) {
commands.add(SET_COMMAND);
}
if ("remove".startsWith(args[0])) {
commands.add(REMOVE_COMMAND);
}
return commands;
}
return Collections.emptySet();
}
private void setAlias(PlotPlayer<?> player, Plot plot, String alias) {
if (alias.isEmpty()) {
sendUsage(player);
} else if (alias.length() >= 50) {
player.sendMessage(TranslatableCaption.of("alias.alias_too_long"));
} else if (MathMan.isInteger(alias)) {
player.sendMessage(TranslatableCaption.of("flag.not_valid_value")); // TODO this is obviously wrong
} else {
if (PlotQuery.newQuery().inArea(plot.getArea())
.withAlias(alias)
.anyMatch()) {
player.sendMessage(
TranslatableCaption.of("alias.alias_is_taken"),
TagResolver.resolver("alias", Tag.inserting(Component.text(alias)))
);
return;
}
if (Settings.UUID.OFFLINE) {
plot.setAlias(alias);
player.sendMessage(
TranslatableCaption.of("alias.alias_set_to"),
TagResolver.resolver("alias", Tag.inserting(Component.text(alias)))
);
return;
}
PlotSquared.get().getImpromptuUUIDPipeline().getSingle(alias, ((uuid, throwable) -> {
if (throwable instanceof TimeoutException) {
player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout"));
} else if (uuid != null) {
player.sendMessage(
TranslatableCaption.of("alias.alias_is_taken"),
TagResolver.resolver("alias", Tag.inserting(Component.text(alias)))
);
} else {
plot.setAlias(alias);
player.sendMessage(
TranslatableCaption.of("alias.alias_set_to"),
TagResolver.resolver("alias", Tag.inserting(Component.text(alias)))
);
}
}));
}
}
private boolean removeAlias(PlotPlayer<?> player, Plot plot) {
String alias = plot.getAlias();
if (!plot.getAlias().isEmpty()) {
player.sendMessage(
TranslatableCaption.of("alias.alias_removed"),
TagResolver.resolver("alias", Tag.inserting(Component.text(alias)))
);
} else {
player.sendMessage(
TranslatableCaption.of("alias.no_alias_set")
);
}
plot.setAlias(null);
return true;
}
private boolean isPermitted(PlotPlayer<?> player, Permission permission) {
return player.hasPermission(permission);
}
}

View File

@ -35,7 +35,6 @@ import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.services.plots.AutoQuery;
import com.plotsquared.core.services.plots.AutoService; import com.plotsquared.core.services.plots.AutoService;
import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.EconHandler;
import com.plotsquared.core.util.EventDispatcher; import com.plotsquared.core.util.EventDispatcher;
@ -327,7 +326,7 @@ public class Auto extends SubCommand {
} }
List<Plot> plots = this.servicePipeline List<Plot> plots = this.servicePipeline
.pump(new AutoQuery(player, null, sizeX, sizeZ, plotarea)) .pump(new AutoService.AutoQuery(player, null, sizeX, sizeZ, plotarea))
.through(AutoService.class) .through(AutoService.class)
.getResult(); .getResult();

View File

@ -108,6 +108,7 @@ public class Clear extends Command {
BackupManager.backup(player, plot, () -> { BackupManager.backup(player, plot, () -> {
final long start = System.currentTimeMillis(); final long start = System.currentTimeMillis();
boolean result = plot.getPlotModificationManager().clear(true, false, player, () -> { boolean result = plot.getPlotModificationManager().clear(true, false, player, () -> {
plot.getPlotModificationManager().unlink();
TaskManager.runTask(() -> { TaskManager.runTask(() -> {
plot.removeRunning(); plot.removeRunning();
// If the state changes, then mark it as no longer done // If the state changes, then mark it as no longer done

View File

@ -85,24 +85,24 @@ public class Inbox extends SubCommand {
for (int x = page * 12; x < max; x++) { for (int x = page * 12; x < max; x++) {
PlotComment comment = comments[x]; PlotComment comment = comments[x];
Component commentColored; Component commentColored;
if (player.getName().equals(comment.senderName())) { if (player.getName().equals(comment.senderName)) {
commentColored = MINI_MESSAGE commentColored = MINI_MESSAGE
.deserialize( .deserialize(
TranslatableCaption.of("list.comment_list_by_lister").getComponent(player), TranslatableCaption.of("list.comment_list_by_lister").getComponent(player),
TagResolver.resolver("comment", Tag.inserting(Component.text(comment.comment()))) TagResolver.resolver("comment", Tag.inserting(Component.text(comment.comment)))
); );
} else { } else {
commentColored = MINI_MESSAGE commentColored = MINI_MESSAGE
.deserialize( .deserialize(
TranslatableCaption.of("list.comment_list_by_other").getComponent(player), TranslatableCaption.of("list.comment_list_by_other").getComponent(player),
TagResolver.resolver("comment", Tag.inserting(Component.text(comment.comment()))) TagResolver.resolver("comment", Tag.inserting(Component.text(comment.comment)))
); );
} }
TagResolver resolver = TagResolver.builder() TagResolver resolver = TagResolver.builder()
.tag("number", Tag.inserting(Component.text(x))) .tag("number", Tag.inserting(Component.text(x)))
.tag("world", Tag.inserting(Component.text(comment.world()))) .tag("world", Tag.inserting(Component.text(comment.world)))
.tag("plot_id", Tag.inserting(Component.text(comment.id().getX() + ";" + comment.id().getY()))) .tag("plot_id", Tag.inserting(Component.text(comment.id.getX() + ";" + comment.id.getY())))
.tag("commenter", Tag.inserting(Component.text(comment.senderName()))) .tag("commenter", Tag.inserting(Component.text(comment.senderName)))
.tag("comment", Tag.inserting(commentColored)) .tag("comment", Tag.inserting(commentColored))
.build(); .build();
builder.append(MINI_MESSAGE builder.append(MINI_MESSAGE
@ -137,7 +137,7 @@ public class Inbox extends SubCommand {
int unread = 0; int unread = 0;
for (PlotComment comment : value) { for (PlotComment comment : value) {
total++; total++;
if (comment.timestamp() > CommentManager if (comment.timestamp > CommentManager
.getTimestamp(player, inbox.toString())) { .getTimestamp(player, inbox.toString())) {
unread++; unread++;
} }
@ -242,7 +242,7 @@ public class Inbox extends SubCommand {
if (success) { if (success) {
player.sendMessage( player.sendMessage(
TranslatableCaption.of("comment.comment_removed_success"), TranslatableCaption.of("comment.comment_removed_success"),
TagResolver.resolver("value", Tag.inserting(Component.text(comment.comment()))) TagResolver.resolver("value", Tag.inserting(Component.text(comment.comment)))
); );
} else { } else {
player.sendMessage( player.sendMessage(

View File

@ -474,20 +474,20 @@ public class ListCmd extends SubCommand {
final List<UUIDMapping> names = PlotSquared.get().getImpromptuUUIDPipeline().getNames(plot.getOwners()) final List<UUIDMapping> names = PlotSquared.get().getImpromptuUUIDPipeline().getNames(plot.getOwners())
.get(Settings.UUID.BLOCKING_TIMEOUT, TimeUnit.MILLISECONDS); .get(Settings.UUID.BLOCKING_TIMEOUT, TimeUnit.MILLISECONDS);
for (final UUIDMapping uuidMapping : names) { for (final UUIDMapping uuidMapping : names) {
PlotPlayer<?> pp = PlotSquared.platform().playerManager().getPlayerIfExists(uuidMapping.uuid()); PlotPlayer<?> pp = PlotSquared.platform().playerManager().getPlayerIfExists(uuidMapping.getUuid());
TagResolver resolver = TagResolver.builder() TagResolver resolver = TagResolver.builder()
.tag("prefix", Tag.inserting(Component.text(prefix))) .tag("prefix", Tag.inserting(Component.text(prefix)))
.tag("player", Tag.inserting(Component.text(uuidMapping.username()))) .tag("player", Tag.inserting(Component.text(uuidMapping.getUsername())))
.build(); .build();
if (pp != null) { if (pp != null) {
builder.append(MINI_MESSAGE.deserialize(online, resolver)); builder.append(MINI_MESSAGE.deserialize(online, resolver));
} else if (uuidMapping.username().equalsIgnoreCase("unknown")) { } else if (uuidMapping.getUsername().equalsIgnoreCase("unknown")) {
TagResolver unknownResolver = TagResolver.resolver( TagResolver unknownResolver = TagResolver.resolver(
"info.unknown", "info.unknown",
Tag.inserting(TranslatableCaption.of("info.unknown").toComponent(player)) Tag.inserting(TranslatableCaption.of("info.unknown").toComponent(player))
); );
builder.append(MINI_MESSAGE.deserialize(unknown, unknownResolver)); builder.append(MINI_MESSAGE.deserialize(unknown, unknownResolver));
} else if (uuidMapping.uuid().equals(DBFunc.EVERYONE)) { } else if (uuidMapping.getUuid().equals(DBFunc.EVERYONE)) {
TagResolver everyoneResolver = TagResolver.resolver( TagResolver everyoneResolver = TagResolver.resolver(
"info.everyone", "info.everyone",
Tag.inserting(TranslatableCaption.of("info.everyone").toComponent(player)) Tag.inserting(TranslatableCaption.of("info.everyone").toComponent(player))

View File

@ -86,7 +86,6 @@ public class MainCommand extends Command {
commands.add(CreateRoadSchematic.class); commands.add(CreateRoadSchematic.class);
commands.add(DebugAllowUnsafe.class); commands.add(DebugAllowUnsafe.class);
commands.add(RegenAllRoads.class); commands.add(RegenAllRoads.class);
commands.add(Claim.class);
commands.add(Auto.class); commands.add(Auto.class);
commands.add(HomeCommand.class); commands.add(HomeCommand.class);
commands.add(Visit.class); commands.add(Visit.class);
@ -94,7 +93,6 @@ public class MainCommand extends Command {
commands.add(Clear.class); commands.add(Clear.class);
commands.add(Delete.class); commands.add(Delete.class);
commands.add(Trust.class); commands.add(Trust.class);
commands.add(Add.class);
commands.add(Leave.class); commands.add(Leave.class);
commands.add(Deny.class); commands.add(Deny.class);
commands.add(Remove.class); commands.add(Remove.class);
@ -130,7 +128,6 @@ public class MainCommand extends Command {
commands.add(Owner.class); commands.add(Owner.class);
commands.add(Desc.class); commands.add(Desc.class);
commands.add(Biome.class); commands.add(Biome.class);
commands.add(Alias.class);
commands.add(SetHome.class); commands.add(SetHome.class);
commands.add(Cluster.class); commands.add(Cluster.class);
commands.add(DebugImportWorlds.class); commands.add(DebugImportWorlds.class);

View File

@ -127,7 +127,7 @@ public class Purge extends SubCommand {
); );
return false; return false;
} }
owner = ownerMapping.uuid(); owner = ownerMapping.getUuid();
break; break;
case "shared": case "shared":
case "s": case "s":
@ -139,7 +139,7 @@ public class Purge extends SubCommand {
); );
return false; return false;
} }
added = addedMapping.uuid(); added = addedMapping.getUuid();
break; break;
case "clear": case "clear":
case "c": case "c":

View File

@ -156,9 +156,9 @@ public class Template extends SubCommand {
ZipOutputStream zos = new ZipOutputStream(fos)) { ZipOutputStream zos = new ZipOutputStream(fos)) {
for (FileBytes file : files) { for (FileBytes file : files) {
ZipEntry ze = new ZipEntry(file.path()); ZipEntry ze = new ZipEntry(file.path);
zos.putNextEntry(ze); zos.putNextEntry(ze);
zos.write(file.data()); zos.write(file.data);
} }
zos.closeEntry(); zos.closeEntry();
} }

View File

@ -0,0 +1,104 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.commands;
import cloud.commandframework.annotations.Argument;
import cloud.commandframework.annotations.CommandMethod;
import cloud.commandframework.annotations.CommandPermission;
import com.google.inject.Inject;
import com.plotsquared.core.commands.arguments.PlotMember;
import com.plotsquared.core.commands.requirements.Requirement;
import com.plotsquared.core.commands.requirements.CommandRequirement;
import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.util.EventDispatcher;
import com.plotsquared.core.util.PlayerManager;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.checkerframework.checker.nullness.qual.NonNull;
class CommandAdd implements PlotSquaredCommandContainer {
private final EventDispatcher eventDispatcher;
@Inject
CommandAdd(final @NonNull EventDispatcher eventDispatcher) {
this.eventDispatcher = eventDispatcher;
}
@Requirement(CommandRequirement.PLAYER)
@Requirement(CommandRequirement.IS_OWNER)
@CommandPermission("plots.add")
@CommandMethod("${command.prefix} add [target]")
public void commandAdd(
final @NonNull PlotPlayer<?> sender,
@Argument("target") final PlotMember target,
final @NonNull Plot plot
) {
if (target instanceof PlotMember.Everyone) {
if (!sender.hasPermission(Permission.PERMISSION_TRUST_EVERYONE) && !sender.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_TRUST)) {
sender.sendMessage(
TranslatableCaption.of("errors.invalid_player"),
TagResolver.resolver("value", Tag.inserting(
PlayerManager.resolveName(target.uuid()).toComponent(sender)
))
);
return;
}
} else if (plot.isOwner(target.uuid())) {
sender.sendMessage(
TranslatableCaption.of("member.already_added"),
TagResolver.resolver("player", Tag.inserting(
PlayerManager.resolveName(target.uuid()).toComponent(sender)
))
);
return;
} else if (plot.getMembers().contains(target.uuid())) {
sender.sendMessage(
TranslatableCaption.of("member.already_added"),
TagResolver.resolver("player", Tag.inserting(
PlayerManager.resolveName(target.uuid()).toComponent(sender)
))
);
return;
} else if (plot.getMembers().size() >= sender.hasPermissionRange(Permission.PERMISSION_ADD, Settings.Limit.MAX_PLOTS)) {
sender.sendMessage(
TranslatableCaption.of("members.plot_max_members_added"),
TagResolver.resolver("amount", Tag.inserting(Component.text(plot.getMembers().size())))
);
return;
}
if (target instanceof PlotMember.Player) {
if (!plot.removeTrusted(target.uuid())) {
if (plot.getDenied().contains(target.uuid())) {
plot.removeDenied(target.uuid());
}
}
}
plot.addMember(target.uuid());
this.eventDispatcher.callMember(sender, plot, target.uuid(), true);
sender.sendMessage(TranslatableCaption.of("member.member_added"));
}
}

View File

@ -0,0 +1,136 @@
package com.plotsquared.core.commands;
import cloud.commandframework.annotations.Argument;
import cloud.commandframework.annotations.CommandMethod;
import cloud.commandframework.annotations.CommandPermission;
import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.commands.requirements.CommandRequirement;
import com.plotsquared.core.commands.requirements.Requirement;
import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.query.PlotQuery;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.tag.Tag;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.concurrent.TimeoutException;
public class CommandAlias implements PlotSquaredCommandContainer {
@Requirement(CommandRequirement.PLAYER)
@Requirement(CommandRequirement.PLOT_HAS_OWNER)
@CommandPermission("plots.alias")
@CommandMethod("${command.prefix} alias set <alias>")
public void commandAliasSet(
final @NonNull PlotPlayer<?> sender,
final @NonNull Plot plot,
@Argument("alias") final @NonNull String alias
) {
final boolean isOwner = plot.isOwner(sender.getUUID());
if (!isOwner && !sender.hasPermission(Permission.PERMISSION_ADMIN_ALIAS_SET)) {
sender.sendMessage(TranslatableCaption.of("permission.no_plot_perms"));
return;
} else if (!sender.hasPermission(Permission.PERMISSION_ALIAS_SET)) {
sender.sendMessage(
TranslatableCaption.of("permission.no_permission"),
TagResolver.resolver(
"node",
Tag.inserting(Permission.PERMISSION_ALIAS_SET)
)
);
return;
}
if (alias.length() >= 50) {
sender.sendMessage(TranslatableCaption.of("alias.alias_too_long"));
return;
}
if (MathMan.isInteger(alias)) {
sender.sendMessage(TranslatableCaption.of("flag.not_valid_value")); // TODO this is obviously wrong
return;
}
if (PlotQuery.newQuery().inArea(plot.getArea())
.withAlias(alias)
.anyMatch()) {
sender.sendMessage(
TranslatableCaption.of("alias.alias_is_taken"),
TagResolver.resolver("alias", Tag.inserting(Component.text(alias)))
);
return;
}
if (Settings.UUID.OFFLINE) {
plot.setAlias(alias);
sender.sendMessage(
TranslatableCaption.of("alias.alias_set_to"),
TagResolver.resolver("alias", Tag.inserting(Component.text(alias)))
);
return;
}
PlotSquared.get().getImpromptuUUIDPipeline().getSingle(alias, ((uuid, throwable) -> {
if (throwable instanceof TimeoutException) {
sender.sendMessage(TranslatableCaption.of("players.fetching_players_timeout"));
} else if (uuid != null) {
sender.sendMessage(
TranslatableCaption.of("alias.alias_is_taken"),
TagResolver.resolver("alias", Tag.inserting(Component.text(alias)))
);
} else {
plot.setAlias(alias);
sender.sendMessage(
TranslatableCaption.of("alias.alias_set_to"),
TagResolver.resolver("alias", Tag.inserting(Component.text(alias)))
);
}
}));
}
@Requirement(CommandRequirement.PLAYER)
@Requirement(CommandRequirement.PLOT_HAS_OWNER)
@CommandPermission("plots.alias")
@CommandMethod("${command.prefix} alias remove")
public void commandAliasRemove(
final @NonNull PlotPlayer<?> sender,
final @NonNull Plot plot
) {
final boolean isOwner = plot.isOwner(sender.getUUID());
if (!isOwner && !sender.hasPermission(Permission.PERMISSION_ADMIN_ALIAS_REMOVE)) {
sender.sendMessage(TranslatableCaption.of("permission.no_plot_perms"));
return;
} else if (!sender.hasPermission(Permission.PERMISSION_ALIAS_REMOVE)) {
sender.sendMessage(
TranslatableCaption.of("permission.no_permission"),
TagResolver.resolver(
"node",
Tag.inserting(Permission.PERMISSION_ALIAS_REMOVE)
)
);
return;
}
if (plot.getAlias().isEmpty()) {
sender.sendMessage(
TranslatableCaption.of("alias.no_alias_set")
);
return;
}
final String currentAlias = plot.getAlias();
plot.setAlias(null);
sender.sendMessage(
TranslatableCaption.of("alias.alias_removed"),
TagResolver.resolver("alias", Tag.inserting(Component.text(currentAlias)))
);
}
}

View File

@ -1,24 +1,11 @@
/* package com.plotsquared.core.commands;
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.command;
import cloud.commandframework.annotations.Argument;
import cloud.commandframework.annotations.CommandMethod;
import cloud.commandframework.annotations.CommandPermission;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.plotsquared.core.commands.requirements.CommandRequirement;
import com.plotsquared.core.commands.requirements.Requirement;
import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.database.DBFunc; import com.plotsquared.core.database.DBFunc;
@ -26,7 +13,6 @@ import com.plotsquared.core.events.PlayerClaimPlotEvent;
import com.plotsquared.core.events.PlotMergeEvent; import com.plotsquared.core.events.PlotMergeEvent;
import com.plotsquared.core.events.Result; import com.plotsquared.core.events.Result;
import com.plotsquared.core.location.Direction; import com.plotsquared.core.location.Direction;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission; import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.MetaDataAccess; import com.plotsquared.core.player.MetaDataAccess;
import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlayerMetaDataKeys;
@ -43,22 +29,17 @@ import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
@CommandDeclaration( public class CommandClaim implements PlotSquaredCommandContainer {
command = "claim",
aliases = "c",
category = CommandCategory.CLAIMING,
requiredType = RequiredType.PLAYER, permission = "plots.claim",
usage = "/plot claim")
public class Claim extends SubCommand {
private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + Claim.class.getSimpleName()); private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + CommandClaim.class.getSimpleName());
private final EventDispatcher eventDispatcher; private final EventDispatcher eventDispatcher;
private final EconHandler econHandler; private final EconHandler econHandler;
@Inject @Inject
public Claim( CommandClaim(
final @NonNull EventDispatcher eventDispatcher, final @NonNull EventDispatcher eventDispatcher,
final @NonNull EconHandler econHandler final @NonNull EconHandler econHandler
) { ) {
@ -66,124 +47,132 @@ public class Claim extends SubCommand {
this.econHandler = econHandler; this.econHandler = econHandler;
} }
@Override @Requirement(CommandRequirement.PLAYER)
public boolean onCommand(final PlotPlayer<?> player, String[] args) { @Requirement(CommandRequirement.IN_PLOT)
String schematic = null; @CommandPermission("plots.add")
if (args.length >= 1) { @CommandMethod("${command.prefix} claim [schematic]")
schematic = args[0]; public void commandClaim(
} final @NonNull PlotPlayer<?> sender,
Location location = player.getLocation(); final @NonNull Plot plot,
Plot plot = location.getPlotAbs(); @Argument("schematic") final @Nullable String schematic
if (plot == null) { ) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot")); final PlayerClaimPlotEvent event = this.eventDispatcher.callClaim(sender, plot, schematic);
return false;
}
final PlayerClaimPlotEvent event = this.eventDispatcher.callClaim(player, plot, schematic);
schematic = event.getSchematic();
if (event.getEventResult() == Result.DENY) { if (event.getEventResult() == Result.DENY) {
player.sendMessage( sender.sendMessage(
TranslatableCaption.of("events.event_denied"), TranslatableCaption.of("events.event_denied"),
TagResolver.resolver("value", Tag.inserting(Component.text("Claim"))) TagResolver.resolver("value", Tag.inserting(Component.text("Claim")))
); );
return true; return;
} }
boolean force = event.getEventResult() == Result.FORCE;
int currentPlots = Settings.Limit.GLOBAL ?
player.getPlotCount() :
player.getPlotCount(location.getWorldName());
final boolean forceClaim = event.getEventResult() == Result.FORCE;
final int currentPlots = Settings.Limit.GLOBAL ?
sender.getPlotCount() :
sender.getPlotCount(sender.getLocation().getWorldName());
final PlotArea area = plot.getArea(); final PlotArea area = plot.getArea();
try (final MetaDataAccess<Integer> metaDataAccess = player.accessPersistentMetaData(PlayerMetaDataKeys.PERSISTENT_GRANTED_PLOTS)) { try (final MetaDataAccess<Integer> metaDataAccess = sender.accessPersistentMetaData(
PlayerMetaDataKeys.PERSISTENT_GRANTED_PLOTS
)) {
int grants = 0; int grants = 0;
if (currentPlots >= player.getAllowedPlots() && !force) { if (currentPlots >= sender.getAllowedPlots() && !forceClaim) {
if (metaDataAccess.isPresent()) { if (metaDataAccess.isPresent()) {
grants = metaDataAccess.get().orElse(0); grants = metaDataAccess.get().orElse(0);
if (grants <= 0) { if (grants <= 0) {
player.sendMessage( sender.sendMessage(
TranslatableCaption.of("permission.cant_claim_more_plots"), TranslatableCaption.of("permission.cant_claim_more_plots"),
TagResolver.resolver("amount", Tag.inserting(Component.text(grants))) TagResolver.resolver("amount", Tag.inserting(Component.text(grants)))
); );
metaDataAccess.remove(); metaDataAccess.remove();
} }
} else { } else {
player.sendMessage( sender.sendMessage(
TranslatableCaption.of("permission.cant_claim_more_plots"), TranslatableCaption.of("permission.cant_claim_more_plots"),
TagResolver.resolver("amount", Tag.inserting(Component.text(player.getAllowedPlots()))) TagResolver.resolver("amount", Tag.inserting(Component.text(sender.getAllowedPlots())))
); );
return false; return;
} }
} }
if (!plot.canClaim(player)) { if (!plot.canClaim(sender)) {
player.sendMessage(TranslatableCaption.of("working.plot_is_claimed")); sender.sendMessage(TranslatableCaption.of("working.plot_is_claimed"));
return false; return;
} }
if (schematic != null && !schematic.isEmpty()) { if (schematic != null && !schematic.isEmpty()) {
if (area.isSchematicClaimSpecify()) { if (area.isSchematicClaimSpecify()) {
if (!area.hasSchematic(schematic)) { if (!area.hasSchematic(schematic)) {
player.sendMessage( sender.sendMessage(
TranslatableCaption.of("schematics.schematic_invalid_named"), TranslatableCaption.of("schematics.schematic_invalid_named"),
TagResolver.builder() TagResolver.builder()
.tag("schemname", Tag.inserting(Component.text(schematic))) .tag("schemname", Tag.inserting(Component.text(schematic)))
.tag("reason", Tag.inserting(Component.text("non-existent"))) .tag("reason", Tag.inserting(Component.text("non-existent")))
.build() .build()
); );
return;
} }
if (!player.hasPermission(Permission.PERMISSION_CLAIM_SCHEMATIC
.format(schematic)) && !player.hasPermission( if (!sender.hasPermission(
Permission.PERMISSION_CLAIM_SCHEMATIC.format(schematic)
) && !sender.hasPermission(
"plots.admin.command.schematic" "plots.admin.command.schematic"
) && !force) { ) && !forceClaim) {
player.sendMessage( sender.sendMessage(
TranslatableCaption.of("permission.no_schematic_permission"), TranslatableCaption.of("permission.no_schematic_permission"),
TagResolver.resolver("value", Tag.inserting(Component.text(schematic))) TagResolver.resolver("value", Tag.inserting(Component.text(schematic)))
); );
return;
} }
} }
} }
if (this.econHandler.isEnabled(area) && !force) {
PlotExpression costExr = area.getPrices().get("claim"); if (this.econHandler.isEnabled(area) && !forceClaim) {
double cost = costExr.evaluate(currentPlots); final PlotExpression costExr = area.getPrices().get("claim");
final double cost = costExr.evaluate(currentPlots);
if (cost > 0d) { if (cost > 0d) {
if (!this.econHandler.isSupported()) { if (!this.econHandler.isSupported()) {
player.sendMessage(TranslatableCaption.of("economy.vault_or_consumer_null")); sender.sendMessage(TranslatableCaption.of("economy.vault_or_consumer_null"));
return false; return;
} }
if (this.econHandler.getMoney(player) < cost) { if (this.econHandler.getMoney(sender) < cost) {
player.sendMessage( sender.sendMessage(
TranslatableCaption.of("economy.cannot_afford_plot"), TranslatableCaption.of("economy.cannot_afford_plot"),
TagResolver.builder() TagResolver.builder()
.tag("money", Tag.inserting(Component.text(this.econHandler.format(cost)))) .tag("money", Tag.inserting(Component.text(this.econHandler.format(cost))))
.tag( .tag(
"balance", "balance",
Tag.inserting(Component.text(this.econHandler.format(this.econHandler.getMoney( Tag.inserting(
player)))) Component.text(this.econHandler.format(this.econHandler.getMoney(sender)))
)
) )
.build() .build()
); );
return false; return;
} }
this.econHandler.withdrawMoney(player, cost); this.econHandler.withdrawMoney(sender, cost);
player.sendMessage( sender.sendMessage(
TranslatableCaption.of("economy.removed_balance"), TranslatableCaption.of("economy.removed_balance"),
TagResolver.builder() TagResolver.builder()
.tag("money", Tag.inserting(Component.text(this.econHandler.format(cost)))) .tag("money", Tag.inserting(Component.text(this.econHandler.format(cost))))
.tag( .tag(
"balance", "balance",
Tag.inserting(Component.text(this.econHandler.format(this.econHandler.getMoney( Tag.inserting(
player)))) Component.text(this.econHandler.format(this.econHandler.getMoney(sender)))
)
) )
.build() .build()
); );
} }
} }
if (grants > 0) { if (grants > 0) {
if (grants == 1) { if (grants == 1) {
metaDataAccess.remove(); metaDataAccess.remove();
} else { } else {
metaDataAccess.set(grants - 1); metaDataAccess.set(grants - 1);
} }
player.sendMessage( sender.sendMessage(
TranslatableCaption.of("economy.removed_granted_plot"), TranslatableCaption.of("economy.removed_granted_plot"),
TagResolver.builder() TagResolver.builder()
.tag("usedGrants", Tag.inserting(Component.text(grants - 1))) .tag("usedGrants", Tag.inserting(Component.text(grants - 1)))
@ -192,27 +181,34 @@ public class Claim extends SubCommand {
); );
} }
} }
if (!player.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_BORDER)) {
int border = area.getBorder(); if (!sender.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_BORDER)) {
if (border != Integer.MAX_VALUE && plot.getDistanceFromOrigin() > border && !force) { final int border = area.getBorder();
player.sendMessage(TranslatableCaption.of("border.denied")); if (border != Integer.MAX_VALUE && plot.getDistanceFromOrigin() > border && !forceClaim) {
return false; sender.sendMessage(TranslatableCaption.of("border.denied"));
return;
} }
} }
plot.setOwnerAbs(player.getUUID());
final String finalSchematic = schematic; // Actually update the owner :)
plot.setOwnerAbs(sender.getUUID());
DBFunc.createPlotSafe(plot, () -> { DBFunc.createPlotSafe(plot, () -> {
try { try {
TaskManager.getPlatformImplementation().sync(() -> { TaskManager.getPlatformImplementation().sync(() -> {
if (!plot.claim(player, true, finalSchematic, false, false)) { if (!plot.claim(sender, true, event.getSchematic(), false, false)) {
LOGGER.info("Failed to claim plot {}", plot.getId().toCommaSeparatedString()); LOGGER.info("Failed to claim plot {}", plot.getId().toCommaSeparatedString());
player.sendMessage(TranslatableCaption.of("working.plot_not_claimed")); sender.sendMessage(TranslatableCaption.of("working.plot_not_claimed"));
plot.setOwnerAbs(null); plot.setOwnerAbs(null);
} else if (area.isAutoMerge()) { } else if (area.isAutoMerge()) {
PlotMergeEvent mergeEvent = Claim.this.eventDispatcher final PlotMergeEvent mergeEvent = this.eventDispatcher.callMerge(
.callMerge(plot, Direction.ALL, Integer.MAX_VALUE, player); plot,
Direction.ALL,
Integer.MAX_VALUE,
sender
);
if (mergeEvent.getEventResult() == Result.DENY) { if (mergeEvent.getEventResult() == Result.DENY) {
player.sendMessage( sender.sendMessage(
TranslatableCaption.of("events.event_denied"), TranslatableCaption.of("events.event_denied"),
TagResolver.resolver("value", Tag.inserting(Component.text("Auto merge on claim"))) TagResolver.resolver("value", Tag.inserting(Component.text("Auto merge on claim")))
); );
@ -220,11 +216,11 @@ public class Claim extends SubCommand {
if (plot.getPlotModificationManager().autoMerge( if (plot.getPlotModificationManager().autoMerge(
mergeEvent.getDir(), mergeEvent.getDir(),
mergeEvent.getMax(), mergeEvent.getMax(),
player.getUUID(), sender.getUUID(),
player, sender,
true true
)) { )) {
eventDispatcher.callPostMerge(player, plot); eventDispatcher.callPostMerge(sender, plot);
} }
} }
} }
@ -235,10 +231,8 @@ public class Claim extends SubCommand {
} }
}, () -> { }, () -> {
LOGGER.info("Failed to add plot to database: {}", plot.getId().toCommaSeparatedString()); LOGGER.info("Failed to add plot to database: {}", plot.getId().toCommaSeparatedString());
player.sendMessage(TranslatableCaption.of("working.plot_not_claimed")); sender.sendMessage(TranslatableCaption.of("working.plot_not_claimed"));
plot.setOwnerAbs(null); plot.setOwnerAbs(null);
}); });
return true;
} }
} }

View File

@ -0,0 +1,26 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.commands;
import cloud.commandframework.captions.Caption;
public final class PlotSquaredCaptionKeys {
public static final Caption ARGUMENT_PARSE_FAILURE_TARGET = Caption.of("argument.parse.failure.target");
}

View File

@ -0,0 +1,26 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.commands;
/**
* Indicates that a class contains commands.
*/
public interface PlotSquaredCommandContainer {
}

View File

@ -0,0 +1,82 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.commands;
import cloud.commandframework.CommandManager;
import cloud.commandframework.annotations.AnnotationParser;
import cloud.commandframework.meta.SimpleCommandMeta;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.plotsquared.core.commands.parsers.PlotMemberParser;
import com.plotsquared.core.commands.requirements.CommandRequirementBuilderModifier;
import com.plotsquared.core.commands.requirements.CommandRequirementPostProcessor;
import com.plotsquared.core.commands.requirements.Requirements;
import com.plotsquared.core.player.PlotPlayer;
import io.leangen.geantyref.TypeToken;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.stream.Stream;
public class PlotSquaredCommandManager {
private final Injector injector;
private final CommandManager<PlotPlayer<?>> commandManager;
private final AnnotationParser<PlotPlayer<?>> annotationParser;
@Inject
public PlotSquaredCommandManager(
final @NonNull Injector injector,
final @NonNull CommandManager<PlotPlayer<?>> commandManager
) {
this.injector = injector;
this.commandManager = commandManager;
this.annotationParser = new AnnotationParser<PlotPlayer<?>>(
this.commandManager,
new TypeToken<PlotPlayer<?>>() {
},
parameters -> SimpleCommandMeta.empty()
);
this.annotationParser.registerBuilderModifier(Requirements.class, new CommandRequirementBuilderModifier());
this.commandManager.registerCommandPostProcessor(new CommandRequirementPostProcessor());
}
/**
* Scans the given {@code instance} for commands, and registers them.
*
* @param instance the instance to scan
*/
public void scanClass(final @NonNull Object instance) {
this.annotationParser.parse(instance);
}
/**
* Initializes all the known commands.
*/
public void initializeCommands() {
// We start by scanning the parsers.
Stream.of(
PlotMemberParser.class
).map(this.injector::getInstance).forEach(this::scanClass);
// Then we scan the commands.
Stream.of(
CommandAdd.class,
CommandClaim.class
).map(this.injector::getInstance).forEach(this::scanClass);
}
}

View File

@ -0,0 +1,94 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.commands.arguments;
import cloud.commandframework.context.CommandContext;
import com.plotsquared.core.commands.parsers.PlotMemberParser;
import com.plotsquared.core.database.DBFunc;
import com.plotsquared.core.player.PlotPlayer;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.UUID;
public sealed interface PlotMember {
PlotMember EVERYONE = new Everyone();
default @NonNull UUID uuid(@NonNull CommandContext<PlotPlayer<?>> context) {
return this.uuid();
}
@NonNull UUID uuid();
sealed interface PlayerLike extends PlotMember {
}
record Player(@NonNull UUID uuid) implements PlayerLike {
}
final class LazyPlayer implements PlayerLike {
private final String candidate;
private final UuidSupplier uuidSupplier;
private @MonotonicNonNull UUID cachedUuid = null;
public LazyPlayer(
final @NonNull String candidate,
final @NonNull UuidSupplier uuidSupplier
) {
this.candidate = candidate;
this.uuidSupplier = uuidSupplier;
}
public @NonNull UUID uuid() {
throw new UnsupportedOperationException();
}
@Override
public synchronized @NonNull UUID uuid(final @NonNull CommandContext<PlotPlayer<?>> context) {
if (this.cachedUuid == null) {
try {
this.cachedUuid = this.uuidSupplier.uuid();
} catch (Exception ignored) {
}
// The player didn't exist :-(
if (this.cachedUuid == null) {
throw new PlotMemberParser.TargetParseException(this.candidate, context);
}
}
return this.cachedUuid;
}
@FunctionalInterface
public interface UuidSupplier {
@Nullable UUID uuid() throws Exception;
}
}
final class Everyone implements PlotMember {
@Override
public @NonNull UUID uuid() {
return DBFunc.EVERYONE;
}
}
}

View File

@ -0,0 +1,124 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.commands.parsers;
import cloud.commandframework.annotations.parsers.Parser;
import cloud.commandframework.captions.CaptionVariable;
import cloud.commandframework.context.CommandContext;
import cloud.commandframework.exceptions.parsing.NoInputProvidedException;
import cloud.commandframework.exceptions.parsing.ParserException;
import com.google.inject.Inject;
import com.plotsquared.core.commands.PlotSquaredCaptionKeys;
import com.plotsquared.core.commands.arguments.PlotMember;
import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.inject.annotations.ImpromptuPipeline;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.uuid.UUIDMapping;
import com.plotsquared.core.uuid.UUIDPipeline;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.io.Serial;
import java.util.Queue;
import java.util.UUID;
public class PlotMemberParser {
private final UUIDPipeline uuidPipeline;
@Inject
public PlotMemberParser(@ImpromptuPipeline final @NonNull UUIDPipeline uuidPipeline) {
this.uuidPipeline = uuidPipeline;
}
@Parser
public @NonNull PlotMember parse(
final @NonNull CommandContext<PlotPlayer<?>> context,
final @NonNull Queue<@NonNull String> input
) {
final var candidate = input.peek();
if (candidate == null) {
throw new NoInputProvidedException(this.getClass(), context);
}
if ("*".equals(candidate)) {
return PlotMember.EVERYONE;
} else if (candidate.length() > 16) {
try {
return new PlotMember.Player(UUID.fromString(candidate));
} catch (IllegalArgumentException ignored) {
throw new TargetParseException(candidate, context);
}
}
if (Settings.Paper_Components.PAPER_LISTENERS) {
try {
return this.uuidPipeline.getUUID(candidate, Settings.UUID.NON_BLOCKING_TIMEOUT)
.get()
.map(UUIDMapping::getUuid)
.map(PlotMember.Player::new)
.orElseThrow();
} catch (Exception e) {
throw new TargetParseException(candidate, context);
}
} else {
return new PlotMember.LazyPlayer(
candidate,
() -> this.uuidPipeline.getUUID(candidate, Settings.UUID.NON_BLOCKING_TIMEOUT)
.get()
.map(UUIDMapping::getUuid)
.orElse(null)
);
}
}
public static final class TargetParseException extends ParserException {
@Serial
private static final long serialVersionUID = 927476591631527552L;
private final String input;
/**
* Construct a new Player parse exception
*
* @param input String input
* @param context Command context
*/
public TargetParseException(
final @NonNull String input,
final @NonNull CommandContext<?> context
) {
super(
PlotMemberParser.class,
context,
PlotSquaredCaptionKeys.ARGUMENT_PARSE_FAILURE_TARGET,
CaptionVariable.of("input", input)
);
this.input = input;
}
/**
* Get the supplied input
*
* @return String value
*/
public @NonNull String getInput() {
return this.input;
}
}
}

View File

@ -0,0 +1,88 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.commands.requirements;
import cloud.commandframework.meta.CommandMeta;
import com.plotsquared.core.configuration.caption.Caption;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.player.ConsolePlayer;
import com.plotsquared.core.player.PlotPlayer;
import io.leangen.geantyref.TypeToken;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
public enum CommandRequirement {
PLAYER(
"",
player -> !(player instanceof ConsolePlayer)
),
IN_PLOT(
"errors.not_in_plot",
player -> player.getCurrentPlot() != null
),
PLOT_HAS_OWNER(
"info.plot_unowned",
player -> Objects.requireNonNull(player.getCurrentPlot()).hasOwner(),
IN_PLOT
),
IS_OWNER(
"permission.no_plot_perms",
player -> Objects.requireNonNull(player.getCurrentPlot()).isOwner(player.getUUID()),
PLOT_HAS_OWNER
);
public static final CommandMeta.Key<List<CommandRequirement>> COMMAND_REQUIREMENTS_KEY = CommandMeta.Key.of(
new TypeToken<List<CommandRequirement>>() {
},
"command_requirements"
);
private final @NonNull Caption caption;
private final @NonNull Predicate<@NonNull PlotPlayer<?>> requirementPredicate;
private final @NonNull Set<@NonNull CommandRequirement> inheritedRequirements;
CommandRequirement(
final @NonNull String caption,
final @NonNull Predicate<@NonNull PlotPlayer<?>> requirementPredicate,
final @NonNull CommandRequirement... inheritedRequirements
) {
this.caption = TranslatableCaption.of(caption);
this.requirementPredicate = requirementPredicate;
this.inheritedRequirements = EnumSet.copyOf(Arrays.asList(inheritedRequirements));
}
public @NonNull Set<@NonNull CommandRequirement> inheritedRequirements() {
return Collections.unmodifiableSet(this.inheritedRequirements);
}
public @NonNull Caption caption() {
return this.caption;
}
public boolean checkRequirement(final @NonNull PlotPlayer<?> player) {
return this.requirementPredicate.test(player);
}
}

View File

@ -0,0 +1,61 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.commands.requirements;
import cloud.commandframework.Command;
import com.plotsquared.core.player.PlotPlayer;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.function.BiFunction;
public class CommandRequirementBuilderModifier implements BiFunction<
@NonNull Requirements,
Command.@NonNull Builder<PlotPlayer<?>>,
Command.@NonNull Builder<PlotPlayer<?>>
> {
@Override
public Command.@NonNull Builder<PlotPlayer<?>> apply(
final @NonNull Requirements requirements,
final Command.@NonNull Builder<PlotPlayer<?>> builder
) {
// We use a list, because we want them to be evaluated in order.
final Set<CommandRequirement> commandRequirements = EnumSet.noneOf(CommandRequirement.class);
for (final Requirement requirement : requirements.value()) {
this.addRequirements(commandRequirements, requirement.value());
}
// We then sort the requirements.
final List<CommandRequirement> sortedRequirements = commandRequirements.stream().sorted().toList();
// We then register all the types in the command metadata.
return builder.meta(CommandRequirement.COMMAND_REQUIREMENTS_KEY, sortedRequirements);
}
private void addRequirements(
final @NonNull Set<@NonNull CommandRequirement> requirements,
final @NonNull CommandRequirement requirement
) {
for (final CommandRequirement inheritedRequirement : requirement.inheritedRequirements()) {
addRequirements(requirements, inheritedRequirement);
}
requirements.add(requirement);
}
}

View File

@ -0,0 +1,54 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.commands.requirements;
import cloud.commandframework.Command;
import cloud.commandframework.execution.postprocessor.CommandPostprocessingContext;
import cloud.commandframework.execution.postprocessor.CommandPostprocessor;
import cloud.commandframework.services.types.ConsumerService;
import com.plotsquared.core.player.PlotPlayer;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.List;
public class CommandRequirementPostProcessor implements CommandPostprocessor<PlotPlayer<?>> {
@Override
public void accept(
@NonNull final CommandPostprocessingContext<PlotPlayer<?>> context
) {
final Command<PlotPlayer<?>> command = context.getCommand();
final PlotPlayer<?> player = context.getCommandContext().getSender();;
final List<CommandRequirement> commandRequirements = command.getCommandMeta().get(
CommandRequirement.COMMAND_REQUIREMENTS_KEY
).orElse(List.of());
for (final CommandRequirement requirement : commandRequirements) {
if (requirement.checkRequirement(player)) {
continue;
}
// They failed the requirement =(
player.sendMessage(requirement.caption());
// Then we interrupt to make sure the command isn't executed.
ConsumerService.interrupt();
}
}
}

View File

@ -0,0 +1,35 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.commands.requirements;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Repeatable(Requirements.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Requirement {
@NonNull CommandRequirement value();
}

View File

@ -0,0 +1,33 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.commands.requirements;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Requirements {
@NonNull Requirement @NonNull[] value();
}

View File

@ -35,15 +35,28 @@ import java.util.Map;
* the component GUI * the component GUI
*/ */
@SerializableAs("preset") @SerializableAs("preset")
public record ComponentPreset( public class ComponentPreset implements ConfigurationSerializable {
ClassicPlotManagerComponent component,
String pattern, private final ClassicPlotManagerComponent component;
double cost, private final String pattern;
String permission, private final double cost;
String displayName, private final String permission;
List<String> description, private final String displayName;
ItemType icon private final List<String> description;
) implements ConfigurationSerializable { private final ItemType icon;
public ComponentPreset(
ClassicPlotManagerComponent component, String pattern, double cost,
String permission, String displayName, List<String> description, final ItemType icon
) {
this.component = component;
this.pattern = pattern;
this.cost = cost;
this.permission = permission;
this.displayName = displayName;
this.description = description;
this.icon = icon;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static ComponentPreset deserialize(final @NonNull Map<String, Object> map) { public static ComponentPreset deserialize(final @NonNull Map<String, Object> map) {
@ -61,6 +74,34 @@ public record ComponentPreset(
); );
} }
public ClassicPlotManagerComponent getComponent() {
return this.component;
}
public String getPattern() {
return this.pattern;
}
public double getCost() {
return this.cost;
}
public String getPermission() {
return this.permission;
}
public String getDisplayName() {
return this.displayName;
}
public List<String> getDescription() {
return this.description;
}
public ItemType getIcon() {
return this.icon;
}
@Override @Override
public Map<String, Object> serialize() { public Map<String, Object> serialize() {
final Map<String, Object> map = new HashMap<>(); final Map<String, Object> map = new HashMap<>();

View File

@ -165,8 +165,8 @@ public class ComponentPresetManager {
final List<ComponentPreset> allowedPresets = new ArrayList<>(this.presets.size()); final List<ComponentPreset> allowedPresets = new ArrayList<>(this.presets.size());
for (final ComponentPreset componentPreset : this.presets) { for (final ComponentPreset componentPreset : this.presets) {
if (!componentPreset.permission().isEmpty() && !player.hasPermission( if (!componentPreset.getPermission().isEmpty() && !player.hasPermission(
componentPreset.permission() componentPreset.getPermission()
)) { )) {
continue; continue;
} }
@ -200,30 +200,30 @@ public class ComponentPresetManager {
return false; return false;
} }
final Pattern pattern = PatternUtil.parse(null, componentPreset.pattern(), false); final Pattern pattern = PatternUtil.parse(null, componentPreset.getPattern(), false);
if (pattern == null) { if (pattern == null) {
getPlayer().sendMessage(TranslatableCaption.of("preset.preset_invalid")); getPlayer().sendMessage(TranslatableCaption.of("preset.preset_invalid"));
return false; return false;
} }
if (componentPreset.cost() > 0.0D) { if (componentPreset.getCost() > 0.0D) {
if (!econHandler.isEnabled(plot.getArea())) { if (!econHandler.isEnabled(plot.getArea())) {
getPlayer().sendMessage( getPlayer().sendMessage(
TranslatableCaption.of("preset.economy_disabled"), TranslatableCaption.of("preset.economy_disabled"),
TagResolver.resolver("preset", Tag.inserting(Component.text(componentPreset.displayName()))) TagResolver.resolver("preset", Tag.inserting(Component.text(componentPreset.getDisplayName())))
); );
return false; return false;
} }
if (econHandler.getMoney(getPlayer()) < componentPreset.cost()) { if (econHandler.getMoney(getPlayer()) < componentPreset.getCost()) {
getPlayer().sendMessage(TranslatableCaption.of("preset.preset_cannot_afford")); getPlayer().sendMessage(TranslatableCaption.of("preset.preset_cannot_afford"));
return false; return false;
} else { } else {
econHandler.withdrawMoney(getPlayer(), componentPreset.cost()); econHandler.withdrawMoney(getPlayer(), componentPreset.getCost());
getPlayer().sendMessage( getPlayer().sendMessage(
TranslatableCaption.of("economy.removed_balance"), TranslatableCaption.of("economy.removed_balance"),
TagResolver.resolver( TagResolver.resolver(
"money", "money",
Tag.inserting(Component.text(econHandler.format(componentPreset.cost()))) Tag.inserting(Component.text(econHandler.format(componentPreset.getCost())))
) )
); );
} }
@ -235,7 +235,7 @@ public class ComponentPresetManager {
queue.setCompleteTask(plot::removeRunning); queue.setCompleteTask(plot::removeRunning);
for (Plot current : plot.getConnectedPlots()) { for (Plot current : plot.getConnectedPlots()) {
current.getPlotModificationManager().setComponent( current.getPlotModificationManager().setComponent(
componentPreset.component().name(), componentPreset.getComponent().name(),
pattern, pattern,
player, player,
queue queue
@ -252,32 +252,32 @@ public class ComponentPresetManager {
for (int i = 0; i < allowedPresets.size(); i++) { for (int i = 0; i < allowedPresets.size(); i++) {
final ComponentPreset preset = allowedPresets.get(i); final ComponentPreset preset = allowedPresets.get(i);
final List<String> lore = new ArrayList<>(); final List<String> lore = new ArrayList<>();
if (preset.cost() > 0) { if (preset.getCost() > 0) {
if (!this.econHandler.isEnabled(plot.getArea())) { if (!this.econHandler.isEnabled(plot.getArea())) {
lore.add(MINI_MESSAGE.serialize(MINI_MESSAGE.deserialize( lore.add(MINI_MESSAGE.serialize(MINI_MESSAGE.deserialize(
TranslatableCaption.of("preset.preset_lore_economy_disabled").getComponent(player)))); TranslatableCaption.of("preset.preset_lore_economy_disabled").getComponent(player))));
} else { } else {
lore.add(MINI_MESSAGE.serialize(MINI_MESSAGE.deserialize( lore.add(MINI_MESSAGE.serialize(MINI_MESSAGE.deserialize(
TranslatableCaption.of("preset.preset_lore_cost").getComponent(player), TranslatableCaption.of("preset.preset_lore_cost").getComponent(player),
TagResolver.resolver("cost", Tag.inserting(Component.text(String.format("%.2f", preset.cost())))) TagResolver.resolver("cost", Tag.inserting(Component.text(String.format("%.2f", preset.getCost()))))
))); )));
} }
} }
lore.add(MINI_MESSAGE.serialize(MINI_MESSAGE.deserialize( lore.add(MINI_MESSAGE.serialize(MINI_MESSAGE.deserialize(
TranslatableCaption.of("preset.preset_lore_component").getComponent(player), TranslatableCaption.of("preset.preset_lore_component").getComponent(player),
TagResolver.builder() TagResolver.builder()
.tag("component", Tag.inserting(Component.text(preset.component().name().toLowerCase()))) .tag("component", Tag.inserting(Component.text(preset.getComponent().name().toLowerCase())))
.tag("prefix", Tag.inserting(TranslatableCaption.of("core.prefix").toComponent(player))) .tag("prefix", Tag.inserting(TranslatableCaption.of("core.prefix").toComponent(player)))
.build() .build()
))); )));
lore.removeIf(String::isEmpty); lore.removeIf(String::isEmpty);
lore.addAll(preset.description()); lore.addAll(preset.getDescription());
plotInventory.setItem( plotInventory.setItem(
i, i,
new PlotItemStack( new PlotItemStack(
preset.icon().getId().replace("minecraft:", ""), preset.getIcon().getId().replace("minecraft:", ""),
1, 1,
preset.displayName(), preset.getDisplayName(),
lore.toArray(new String[0]) lore.toArray(new String[0])
) )
); );

View File

@ -2400,13 +2400,13 @@ public class SQLManager implements AbstractDB {
if (plot != null) { if (plot != null) {
statement.setString(1, plot.getArea().toString()); statement.setString(1, plot.getArea().toString());
statement.setInt(2, plot.getId().hashCode()); statement.setInt(2, plot.getId().hashCode());
statement.setString(3, comment.comment()); statement.setString(3, comment.comment);
statement.setString(4, comment.inbox()); statement.setString(4, comment.inbox);
statement.setString(5, comment.senderName()); statement.setString(5, comment.senderName);
} else { } else {
statement.setString(1, comment.comment()); statement.setString(1, comment.comment);
statement.setString(2, comment.inbox()); statement.setString(2, comment.inbox);
statement.setString(3, comment.senderName()); statement.setString(3, comment.senderName);
} }
} }
@ -2518,10 +2518,10 @@ public class SQLManager implements AbstractDB {
public void set(PreparedStatement statement) throws SQLException { public void set(PreparedStatement statement) throws SQLException {
statement.setString(1, plot.getArea().toString()); statement.setString(1, plot.getArea().toString());
statement.setInt(2, plot.getId().hashCode()); statement.setInt(2, plot.getId().hashCode());
statement.setString(3, comment.comment()); statement.setString(3, comment.comment);
statement.setString(4, comment.inbox()); statement.setString(4, comment.inbox);
statement.setInt(5, (int) (comment.timestamp() / 1000)); statement.setInt(5, (int) (comment.timestamp / 1000));
statement.setString(6, comment.senderName()); statement.setString(6, comment.senderName);
} }
@Override @Override
@ -3414,10 +3414,15 @@ public class SQLManager implements AbstractDB {
} }
} }
private record LegacySettings( private static class LegacySettings {
int id,
PlotSettings settings public final int id;
) { public final PlotSettings settings;
public LegacySettings(int id, PlotSettings settings) {
this.id = id;
this.settings = settings;
}
} }

View File

@ -18,7 +18,6 @@
*/ */
package com.plotsquared.core.events; package com.plotsquared.core.events;
import com.plotsquared.core.command.Claim;
import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotArea;

View File

@ -18,7 +18,6 @@
*/ */
package com.plotsquared.core.events; package com.plotsquared.core.events;
import com.plotsquared.core.command.Claim;
import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;

View File

@ -341,14 +341,14 @@ public class PlotListener {
} }
TimedFlag.Timed<Integer> feed = plot.getFlag(FeedFlag.class); TimedFlag.Timed<Integer> feed = plot.getFlag(FeedFlag.class);
if (feed.interval() != 0 && feed.value() != 0) { if (feed.getInterval() != 0 && feed.getValue() != 0) {
feedRunnable feedRunnable
.put(player.getUUID(), new Interval(feed.interval(), feed.value(), 20)); .put(player.getUUID(), new Interval(feed.getInterval(), feed.getValue(), 20));
} }
TimedFlag.Timed<Integer> heal = plot.getFlag(HealFlag.class); TimedFlag.Timed<Integer> heal = plot.getFlag(HealFlag.class);
if (heal.interval() != 0 && heal.value() != 0) { if (heal.getInterval() != 0 && heal.getValue() != 0) {
healRunnable healRunnable
.put(player.getUUID(), new Interval(heal.interval(), heal.value(), 20)); .put(player.getUUID(), new Interval(heal.getInterval(), heal.getValue(), 20));
} }
return true; return true;
} }

View File

@ -21,11 +21,17 @@ package com.plotsquared.core.location;
import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.StringMan;
public record ChunkWrapper( public class ChunkWrapper {
String world,
int x, public final int x;
int z public final int z;
) { public final String world;
public ChunkWrapper(String world, int x, int z) {
this.world = world;
this.x = x;
this.z = z;
}
@Override @Override
public int hashCode() { public int hashCode() {

View File

@ -288,7 +288,7 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer,
* *
* @return the plot the player is standing on or null if standing on a road or not in a {@link PlotArea} * @return the plot the player is standing on or null if standing on a road or not in a {@link PlotArea}
*/ */
public Plot getCurrentPlot() { public @Nullable Plot getCurrentPlot() {
try (final MetaDataAccess<Plot> lastPlotAccess = try (final MetaDataAccess<Plot> lastPlotAccess =
this.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { this.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) {
if (lastPlotAccess.get().orElse(null) == null && !Settings.Enabled_Components.EVENTS) { if (lastPlotAccess.get().orElse(null) == null && !Settings.Enabled_Components.EVENTS) {

View File

@ -215,48 +215,66 @@ public final class BlockBucket implements ConfigurationSerializable {
return result; return result;
} }
private record Range( private static final class Range {
int min,
int max,
boolean automatic
) {
public int getWeight() { private final int min;
return max - min; private final int max;
} private final boolean automatic;
public boolean isInRange(final int num) {
return num <= max && num >= min;
}
public boolean equals(final Object o) {
if (o == this) {
return true;
}
if (!(o instanceof final Range other)) {
return false;
}
if (this.min() != other.min()) {
return false;
}
if (this.max() != other.max()) {
return false;
}
if (this.automatic() != other.automatic()) {
return false;
}
return true;
}
public int hashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + this.min();
result = result * PRIME + this.max();
result = result * PRIME + (this.automatic() ? 79 : 97);
return result;
}
public Range(int min, int max, boolean automatic) {
this.min = min;
this.max = max;
this.automatic = automatic;
} }
public int getWeight() {
return max - min;
}
public boolean isInRange(final int num) {
return num <= max && num >= min;
}
public int getMin() {
return this.min;
}
public int getMax() {
return this.max;
}
public boolean equals(final Object o) {
if (o == this) {
return true;
}
if (!(o instanceof final Range other)) {
return false;
}
if (this.getMin() != other.getMin()) {
return false;
}
if (this.getMax() != other.getMax()) {
return false;
}
if (this.isAutomatic() != other.isAutomatic()) {
return false;
}
return true;
}
public int hashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + this.getMin();
result = result * PRIME + this.getMax();
result = result * PRIME + (this.isAutomatic() ? 79 : 97);
return result;
}
public boolean isAutomatic() {
return this.automatic;
}
}
} }

View File

@ -113,12 +113,13 @@ public class PlotSettings {
this.position = position; this.position = position;
} }
@SuppressWarnings({"UnstableApiUsage"})
public List<PlotComment> getComments(String inbox) { public List<PlotComment> getComments(String inbox) {
if (this.comments == null) { if (this.comments == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
return this.comments.stream().filter(comment -> comment.inbox().equals(inbox)) return this.comments.stream().filter(comment -> comment.inbox.equals(inbox))
.collect(ImmutableList.toImmutableList()); .collect(ImmutableList.toImmutableList());
} }

View File

@ -58,7 +58,7 @@ public class CommentManager {
if (value != null) { if (value != null) {
int num = 0; int num = 0;
for (PlotComment comment : value) { for (PlotComment comment : value) {
if (comment.timestamp() > getTimestamp(player, inbox.toString())) { if (comment.timestamp > getTimestamp(player, inbox.toString())) {
num++; num++;
} }
} }

View File

@ -20,13 +20,25 @@ package com.plotsquared.core.plot.comment;
import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.plot.PlotId;
public record PlotComment( public class PlotComment {
String world,
PlotId id, public final String comment;
String comment, public final String inbox;
String senderName, public final String senderName;
String inbox, public final PlotId id;
long timestamp public final String world;
) { public final long timestamp;
public PlotComment(
String world, PlotId id, String comment, String senderName, String inbox,
long timestamp
) {
this.world = world;
this.id = id;
this.comment = comment;
this.senderName = senderName;
this.inbox = inbox;
this.timestamp = timestamp;
}
} }

View File

@ -60,7 +60,7 @@ public class FeedFlag extends TimedFlag<Integer, FeedFlag> {
@Override @Override
protected Integer mergeValue(Integer other) { protected Integer mergeValue(Integer other) {
return this.getValue().value() + other; return this.getValue().getValue() + other;
} }
@Override @Override

View File

@ -60,7 +60,7 @@ public class HealFlag extends TimedFlag<Integer, HealFlag> {
@Override @Override
protected Integer mergeValue(Integer other) { protected Integer mergeValue(Integer other) {
return this.getValue().value() + other; return this.getValue().getValue() + other;
} }
@Override @Override

View File

@ -76,16 +76,29 @@ public abstract class TimedFlag<T, F extends PlotFlag<TimedFlag.Timed<T>, F>>
return getValue().toString(); return getValue().toString();
} }
public record Timed<T>( public static final class Timed<T> {
int interval,
T value
) {
@Override private final int interval;
public String toString() { private final T value;
return String.format("%d %s", interval, value);
}
public Timed(int interval, T value) {
this.interval = interval;
this.value = value;
} }
public int getInterval() {
return interval;
}
public T getValue() {
return value;
}
@Override
public String toString() {
return String.format("%d %s", interval, value);
}
}
} }

View File

@ -1,105 +0,0 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.services.plots;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotId;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
public record AutoQuery(
PlotPlayer<?> player,
PlotId startId,
int sizeX,
int sizeZ,
PlotArea plotArea
) {
/**
* Crate a new auto query
*
* @param player Player to claim for
* @param startId Plot ID to start searching from
* @param sizeX Number of plots along the X axis
* @param sizeZ Number of plots along the Z axis
* @param plotArea Plot area to search in
*/
public AutoQuery(
final @NonNull PlotPlayer<?> player, final @Nullable PlotId startId,
final int sizeX, final int sizeZ, final @NonNull PlotArea plotArea
) {
this.player = player;
this.startId = startId;
this.sizeX = sizeX;
this.sizeZ = sizeZ;
this.plotArea = plotArea;
}
/**
* Get the player that the plots are meant for
*
* @return Player
*/
@Override
public @NonNull PlotPlayer<?> player() {
return this.player;
}
/**
* Get the plot ID to start searching from
*
* @return Start ID
*/
@Override
public @Nullable PlotId startId() {
return this.startId;
}
/**
* Get the number of plots along the X axis
*
* @return Number of plots along the X axis
*/
@Override
public int sizeX() {
return this.sizeX;
}
/**
* Get the number of plots along the Z axis
*
* @return Number of plots along the Z axis
*/
@Override
public int sizeZ() {
return this.sizeZ;
}
/**
* Get the plot area to search in
*
* @return Plot area
*/
@Override
public @NonNull PlotArea plotArea() {
return this.plotArea;
}
}

View File

@ -21,7 +21,9 @@ package com.plotsquared.core.services.plots;
import cloud.commandframework.services.types.Service; import cloud.commandframework.services.types.Service;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotAreaType; import com.plotsquared.core.plot.PlotAreaType;
import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.plot.PlotId;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
@ -32,12 +34,88 @@ import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Predicate; import java.util.function.Predicate;
public interface AutoService extends Service<AutoQuery, List<Plot>> { public interface AutoService extends Service<AutoService.AutoQuery, List<Plot>> {
Cache<PlotId, Plot> plotCandidateCache = CacheBuilder.newBuilder() Cache<PlotId, Plot> plotCandidateCache = CacheBuilder.newBuilder()
.expireAfterWrite(20, TimeUnit.SECONDS).build(); .expireAfterWrite(20, TimeUnit.SECONDS).build();
Object plotLock = new Object(); Object plotLock = new Object();
final class AutoQuery {
private final PlotPlayer<?> player;
private final PlotId startId;
private final int sizeX;
private final int sizeZ;
private final PlotArea plotArea;
/**
* Crate a new auto query
*
* @param player Player to claim for
* @param startId Plot ID to start searching from
* @param sizeX Number of plots along the X axis
* @param sizeZ Number of plots along the Z axis
* @param plotArea Plot area to search in
*/
public AutoQuery(
final @NonNull PlotPlayer<?> player, final @Nullable PlotId startId,
final int sizeX, final int sizeZ, final @NonNull PlotArea plotArea
) {
this.player = player;
this.startId = startId;
this.sizeX = sizeX;
this.sizeZ = sizeZ;
this.plotArea = plotArea;
}
/**
* Get the player that the plots are meant for
*
* @return Player
*/
public @NonNull PlotPlayer<?> getPlayer() {
return this.player;
}
/**
* Get the plot ID to start searching from
*
* @return Start ID
*/
public @Nullable PlotId getStartId() {
return this.startId;
}
/**
* Get the number of plots along the X axis
*
* @return Number of plots along the X axis
*/
public int getSizeX() {
return this.sizeX;
}
/**
* Get the number of plots along the Z axis
*
* @return Number of plots along the Z axis
*/
public int getSizeZ() {
return this.sizeZ;
}
/**
* Get the plot area to search in
*
* @return Plot area
*/
public @NonNull PlotArea getPlotArea() {
return this.plotArea;
}
}
final class DefaultAutoService implements AutoService { final class DefaultAutoService implements AutoService {
@Override @Override
@ -47,16 +125,17 @@ public interface AutoService extends Service<AutoQuery, List<Plot>> {
} }
final class SinglePlotService implements AutoService, Predicate<AutoQuery> { final class SinglePlotService implements AutoService, Predicate<AutoQuery> {
@Nullable @Nullable
@Override @Override
public List<Plot> handle(@NonNull AutoQuery autoQuery) { public List<Plot> handle(@NonNull AutoQuery autoQuery) {
Plot plot; Plot plot;
PlotId nextId = autoQuery.startId(); PlotId nextId = autoQuery.getStartId();
do { do {
synchronized (plotLock) { synchronized (plotLock) {
plot = autoQuery.plotArea().getNextFreePlot(autoQuery.player(), nextId); plot = autoQuery.getPlotArea().getNextFreePlot(autoQuery.getPlayer(), nextId);
if (plot != null && plotCandidateCache.getIfPresent(plot.getId()) == null) { if (plot != null && plotCandidateCache.getIfPresent(plot.getId()) == null) {
plotCandidateCache.put(plot.getId(), plot); plotCandidateCache.put(plot.getId(), plot);
return Collections.singletonList(plot); return Collections.singletonList(plot);
@ -72,11 +151,12 @@ public interface AutoService extends Service<AutoQuery, List<Plot>> {
@Override @Override
public boolean test(final @NonNull AutoQuery autoQuery) { public boolean test(final @NonNull AutoQuery autoQuery) {
return autoQuery.sizeX() == 1 && autoQuery.sizeZ() == 1; return autoQuery.sizeX == 1 && autoQuery.sizeZ == 1;
} }
} }
final class MultiPlotService implements AutoService, Predicate<AutoQuery> { final class MultiPlotService implements AutoService, Predicate<AutoQuery> {
@Override @Override
@ -86,14 +166,14 @@ public interface AutoService extends Service<AutoQuery, List<Plot>> {
while (true) { while (true) {
synchronized (plotLock) { synchronized (plotLock) {
final PlotId start = final PlotId start =
autoQuery.plotArea().getMeta("lastPlot", PlotId.of(0, 0)).getNextId(); autoQuery.getPlotArea().getMeta("lastPlot", PlotId.of(0, 0)).getNextId();
final PlotId end = PlotId.of( final PlotId end = PlotId.of(
start.getX() + autoQuery.sizeX() - 1, start.getX() + autoQuery.getSizeX() - 1,
start.getY() + autoQuery.sizeZ() - 1 start.getY() + autoQuery.getSizeZ() - 1
); );
final List<Plot> plots = final List<Plot> plots =
autoQuery.plotArea().canClaim(autoQuery.player(), start, end); autoQuery.getPlotArea().canClaim(autoQuery.getPlayer(), start, end);
autoQuery.plotArea().setMeta("lastPlot", start); // set entry point for next try autoQuery.getPlotArea().setMeta("lastPlot", start); // set entry point for next try
if (plots != null && !plots.isEmpty()) { if (plots != null && !plots.isEmpty()) {
for (final Plot plot : plots) { for (final Plot plot : plots) {
if (plotCandidateCache.getIfPresent(plot.getId()) != null) { if (plotCandidateCache.getIfPresent(plot.getId()) != null) {
@ -109,7 +189,7 @@ public interface AutoService extends Service<AutoQuery, List<Plot>> {
@Override @Override
public boolean test(final @NonNull AutoQuery autoQuery) { public boolean test(final @NonNull AutoQuery autoQuery) {
return autoQuery.plotArea().getType() != PlotAreaType.PARTIAL; return autoQuery.getPlotArea().getType() != PlotAreaType.PARTIAL;
} }
} }

View File

@ -48,10 +48,10 @@ public class SettingsNodeStep implements SetupStep {
) { ) {
this.configurationNode = configurationNode; this.configurationNode = configurationNode;
this.id = id; this.id = id;
if (wrapper.settingsNodes().length > id + 1) { if (wrapper.getSettingsNodes().length > id + 1) {
this.next = new SettingsNodeStep(wrapper.settingsNodes()[id + 1], id + 1, wrapper); this.next = new SettingsNodeStep(wrapper.getSettingsNodes()[id + 1], id + 1, wrapper);
} else { } else {
this.next = wrapper.afterwards(); this.next = wrapper.getAfterwards();
} }
} }

View File

@ -23,10 +23,15 @@ import com.plotsquared.core.configuration.ConfigurationNode;
/** /**
* This class wraps an array of {@link ConfigurationNode}s. * This class wraps an array of {@link ConfigurationNode}s.
*/ */
public record SettingsNodesWrapper( public class SettingsNodesWrapper {
ConfigurationNode[] settingsNodes,
SetupStep afterwards private final ConfigurationNode[] settingsNodes;
) { private final SetupStep afterwards;
public SettingsNodesWrapper(final ConfigurationNode[] settingsNodes, final SetupStep afterwards) {
this.settingsNodes = settingsNodes;
this.afterwards = afterwards;
}
/** /**
* Returns the first step of this wrapper or the step or the * Returns the first step of this wrapper or the step or the
@ -38,4 +43,12 @@ public record SettingsNodesWrapper(
return this.settingsNodes.length == 0 ? this.afterwards : new SettingsNodeStep(this.settingsNodes[0], 0, this); return this.settingsNodes.length == 0 ? this.afterwards : new SettingsNodeStep(this.settingsNodes[0], 0, this);
} }
public ConfigurationNode[] getSettingsNodes() {
return this.settingsNodes;
}
public SetupStep getAfterwards() {
return this.afterwards;
}
} }

View File

@ -18,9 +18,14 @@
*/ */
package com.plotsquared.core.util; package com.plotsquared.core.util;
public record FileBytes( public class FileBytes {
String path,
byte[] data public final String path;
) { public final byte[] data;
public FileBytes(String path, byte[] data) {
this.path = path;
this.data = data;
}
} }

View File

@ -98,7 +98,7 @@ public abstract class PlayerManager<P extends PlotPlayer<? extends T>, T> {
consumer.accept(null, throwable); consumer.accept(null, throwable);
} else { } else {
for (final UUIDMapping uuid : uuids) { for (final UUIDMapping uuid : uuids) {
result.add(uuid.uuid()); result.add(uuid.getUuid());
} }
consumer.accept(result, null); consumer.accept(result, null);
} }
@ -136,7 +136,7 @@ public abstract class PlayerManager<P extends PlotPlayer<? extends T>, T> {
try { try {
for (final UUIDMapping mapping : PlotSquared.get().getImpromptuUUIDPipeline() for (final UUIDMapping mapping : PlotSquared.get().getImpromptuUUIDPipeline()
.getNames(players).get(Settings.UUID.BLOCKING_TIMEOUT, TimeUnit.MILLISECONDS)) { .getNames(players).get(Settings.UUID.BLOCKING_TIMEOUT, TimeUnit.MILLISECONDS)) {
users.add(Component.text(mapping.username())); users.add(Component.text(mapping.getUsername()));
} }
} catch (final Exception e) { } catch (final Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -200,7 +200,7 @@ public abstract class PlayerManager<P extends PlotPlayer<? extends T>, T> {
final UUIDMapping uuidMapping = final UUIDMapping uuidMapping =
PlotSquared.get().getImpromptuUUIDPipeline().getImmediately(owner); PlotSquared.get().getImpromptuUUIDPipeline().getImmediately(owner);
if (uuidMapping != null) { if (uuidMapping != null) {
name = uuidMapping.username(); name = uuidMapping.getUsername();
} else { } else {
name = null; name = null;
} }

View File

@ -238,8 +238,8 @@ public final class TabCompletions {
PlotSquared.get().getImpromptuUUIDPipeline().getAllImmediately(); PlotSquared.get().getImpromptuUUIDPipeline().getAllImmediately();
players = new ArrayList<>(mappings.size()); players = new ArrayList<>(mappings.size());
for (final UUIDMapping mapping : mappings) { for (final UUIDMapping mapping : mappings) {
if (uuidFilter.test(mapping.uuid())) { if (uuidFilter.test(mapping.getUuid())) {
players.add(mapping.username()); players.add(mapping.getUsername());
} }
} }
cachedCompletionValues.put(cacheIdentifier, players); cachedCompletionValues.put(cacheIdentifier, players);

View File

@ -298,11 +298,19 @@ public final class PlaceholderRegistry {
} }
/** /**
* Event called when a new {@link Placeholder} has been added * Event called when a new {@link Placeholder} has been added
*/ */
public record PlaceholderAddedEvent( public static class PlaceholderAddedEvent {
Placeholder placeholder
) { private final Placeholder placeholder;
public PlaceholderAddedEvent(Placeholder placeholder) {
this.placeholder = placeholder;
}
public Placeholder getPlaceholder() {
return this.placeholder;
}
} }

View File

@ -67,8 +67,8 @@ public class CacheUUIDService implements UUIDService, Consumer<List<UUIDMapping>
@Override @Override
public void accept(final @NonNull List<@NonNull UUIDMapping> uuidMappings) { public void accept(final @NonNull List<@NonNull UUIDMapping> uuidMappings) {
for (final UUIDMapping mapping : uuidMappings) { for (final UUIDMapping mapping : uuidMappings) {
this.uuidCache.put(mapping.uuid(), mapping); this.uuidCache.put(mapping.getUuid(), mapping);
this.usernameCache.put(mapping.username(), mapping); this.usernameCache.put(mapping.getUsername(), mapping);
} }
} }

View File

@ -20,15 +20,29 @@ package com.plotsquared.core.uuid;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
/** /**
* A pair consisting of a UUID and a username * A pair consisting of a UUID and a username
*/ */
public record UUIDMapping( public class UUIDMapping {
@NonNull UUID uuid,
@NonNull String username private final UUID uuid;
) { private final String username;
public UUIDMapping(final @NonNull UUID uuid, final @NonNull String username) {
this.uuid = uuid;
this.username = username;
}
public @NonNull String getUsername() {
return this.username;
}
public @NonNull UUID getUuid() {
return this.uuid;
}
@Override @Override
public boolean equals(final Object o) { public boolean equals(final Object o) {
@ -42,4 +56,9 @@ public record UUIDMapping(
return uuid.equals(that.uuid) && username.equals(that.username); return uuid.equals(that.uuid) && username.equals(that.username);
} }
@Override
public int hashCode() {
return Objects.hash(uuid, username);
}
} }

View File

@ -36,6 +36,7 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -157,7 +158,7 @@ public class UUIDPipeline {
TimeUnit.MILLISECONDS TimeUnit.MILLISECONDS
); );
if (mappings.size() == 1) { if (mappings.size() == 1) {
return mappings.get(0).uuid(); return mappings.get(0).getUuid();
} }
} catch (InterruptedException | ExecutionException e) { } catch (InterruptedException | ExecutionException e) {
e.printStackTrace(); e.printStackTrace();
@ -182,7 +183,7 @@ public class UUIDPipeline {
try { try {
final List<UUIDMapping> mappings = this.getNames(Collections.singletonList(uuid)).get(timeout, TimeUnit.MILLISECONDS); final List<UUIDMapping> mappings = this.getNames(Collections.singletonList(uuid)).get(timeout, TimeUnit.MILLISECONDS);
if (mappings.size() == 1) { if (mappings.size() == 1) {
return mappings.get(0).username(); return mappings.get(0).getUsername();
} }
} catch (InterruptedException | ExecutionException e) { } catch (InterruptedException | ExecutionException e) {
e.printStackTrace(); e.printStackTrace();
@ -209,7 +210,7 @@ public class UUIDPipeline {
uuid.accept(null, throwable); uuid.accept(null, throwable);
} else { } else {
if (!uuids.isEmpty()) { if (!uuids.isEmpty()) {
uuid.accept(uuids.get(0).uuid(), null); uuid.accept(uuids.get(0).getUuid(), null);
} else { } else {
uuid.accept(null, null); uuid.accept(null, null);
} }
@ -231,7 +232,7 @@ public class UUIDPipeline {
username.accept(null, throwable); username.accept(null, throwable);
} else { } else {
if (!uuids.isEmpty()) { if (!uuids.isEmpty()) {
username.accept(uuids.get(0).username(), null); username.accept(uuids.get(0).getUsername(), null);
} else { } else {
username.accept(null, null); username.accept(null, null);
} }
@ -273,6 +274,25 @@ public class UUIDPipeline {
return this.getUUIDs(requests).orTimeout(timeout, TimeUnit.MILLISECONDS); return this.getUUIDs(requests).orTimeout(timeout, TimeUnit.MILLISECONDS);
} }
/**
* Asynchronously attempt to fetch the mapping from a name.
* <p>
* This will timeout after the specified time and throws a {@link TimeoutException}
* if this happens
*
* @param username Name
* @param timeout Timeout in milliseconds
* @return Mapping
*/
public @NonNull CompletableFuture<Optional<UUIDMapping>> getUUID(
final @NonNull String username,
final long timeout
) {
return this.getUUIDs(List.of(username), timeout).thenApply(
results -> results.stream().findFirst()
);
}
/** /**
* Asynchronously attempt to fetch the mapping from a list of UUIDs * Asynchronously attempt to fetch the mapping from a list of UUIDs
* *
@ -296,7 +316,7 @@ public class UUIDPipeline {
if (service.canBeSynchronous()) { if (service.canBeSynchronous()) {
final List<UUIDMapping> completedRequests = service.getNames(remainingRequests); final List<UUIDMapping> completedRequests = service.getNames(remainingRequests);
for (final UUIDMapping mapping : completedRequests) { for (final UUIDMapping mapping : completedRequests) {
remainingRequests.remove(mapping.uuid()); remainingRequests.remove(mapping.getUuid());
} }
mappings.addAll(completedRequests); mappings.addAll(completedRequests);
} else { } else {
@ -311,7 +331,7 @@ public class UUIDPipeline {
for (final UUIDService service : serviceList) { for (final UUIDService service : serviceList) {
final List<UUIDMapping> completedRequests = service.getNames(remainingRequests); final List<UUIDMapping> completedRequests = service.getNames(remainingRequests);
for (final UUIDMapping mapping : completedRequests) { for (final UUIDMapping mapping : completedRequests) {
remainingRequests.remove(mapping.uuid()); remainingRequests.remove(mapping.getUuid());
} }
mappings.addAll(completedRequests); mappings.addAll(completedRequests);
if (remainingRequests.isEmpty()) { if (remainingRequests.isEmpty()) {
@ -365,7 +385,7 @@ public class UUIDPipeline {
if (service.canBeSynchronous()) { if (service.canBeSynchronous()) {
final List<UUIDMapping> completedRequests = service.getUUIDs(remainingRequests); final List<UUIDMapping> completedRequests = service.getUUIDs(remainingRequests);
for (final UUIDMapping mapping : completedRequests) { for (final UUIDMapping mapping : completedRequests) {
remainingRequests.remove(mapping.username()); remainingRequests.remove(mapping.getUsername());
} }
mappings.addAll(completedRequests); mappings.addAll(completedRequests);
} else { } else {
@ -380,7 +400,7 @@ public class UUIDPipeline {
for (final UUIDService service : serviceList) { for (final UUIDService service : serviceList) {
final List<UUIDMapping> completedRequests = service.getUUIDs(remainingRequests); final List<UUIDMapping> completedRequests = service.getUUIDs(remainingRequests);
for (final UUIDMapping mapping : completedRequests) { for (final UUIDMapping mapping : completedRequests) {
remainingRequests.remove(mapping.username()); remainingRequests.remove(mapping.getUsername());
} }
mappings.addAll(completedRequests); mappings.addAll(completedRequests);
if (remainingRequests.isEmpty()) { if (remainingRequests.isEmpty()) {

View File

@ -155,7 +155,7 @@ subprojects {
id.set("NotMyFault") id.set("NotMyFault")
name.set("Alexander Brandes") name.set("Alexander Brandes")
organization.set("IntellectualSites") organization.set("IntellectualSites")
email.set("contact(at)notmyfault.dev") email.set("contact@notmyfault.dev")
} }
developer { developer {
id.set("SirYwell") id.set("SirYwell")

View File

@ -11,17 +11,17 @@ essentialsx = "2.19.7"
mvdwapi = "3.1.1" mvdwapi = "3.1.1"
# Third party # Third party
prtree = "2.0.1" prtree = "2.0.0"
aopalliance = "1.0" aopalliance = "1.0"
cloud-services = "1.8.2"
arkitektonika = "2.1.1" arkitektonika = "2.1.1"
squirrelid = "0.3.1" squirrelid = "0.3.1"
cloud = "1.8.0"
# Gradle plugins # Gradle plugins
shadow = "7.1.2" shadow = "7.1.2"
grgit = "4.1.1" grgit = "4.1.1"
spotless = "6.16.0" spotless = "6.15.0"
nexus = "1.2.0" nexus = "1.1.0"
[libraries] [libraries]
# Platform expectations # Platform expectations
@ -39,10 +39,14 @@ essentialsx = { group = "net.essentialsx", name = "EssentialsX", version.ref = "
# Third party # Third party
prtree = { group = "com.intellectualsites.prtree", name = "PRTree", version.ref = "prtree" } prtree = { group = "com.intellectualsites.prtree", name = "PRTree", version.ref = "prtree" }
aopalliance = { group = "aopalliance", name = "aopalliance", version.ref = "aopalliance" } aopalliance = { group = "aopalliance", name = "aopalliance", version.ref = "aopalliance" }
cloudServices = { group = "cloud.commandframework", name = "cloud-services", version.ref = "cloud-services" }
mvdwapi = { group = "com.intellectualsites.mvdwplaceholderapi", name = "MVdWPlaceholderAPI", version.ref = "mvdwapi" } mvdwapi = { group = "com.intellectualsites.mvdwplaceholderapi", name = "MVdWPlaceholderAPI", version.ref = "mvdwapi" }
squirrelid = { group = "org.enginehub", name = "squirrelid", version.ref = "squirrelid" } squirrelid = { group = "org.enginehub", name = "squirrelid", version.ref = "squirrelid" }
arkitektonika = { group = "com.intellectualsites.arkitektonika", name = "Arkitektonika-Client", version.ref = "arkitektonika" } arkitektonika = { group = "com.intellectualsites.arkitektonika", name = "Arkitektonika-Client", version.ref = "arkitektonika" }
cloudServices = { group = "cloud.commandframework", name = "cloud-services", version.ref = "cloud" }
cloudCore = { group = "cloud.commandframework", name = "cloud-core", version.ref = "cloud" }
cloudAnnotations = { group = "cloud.commandframework", name = "cloud-annotations", version.ref = "cloud" }
cloudPaper = { group = "cloud.commandframework", name = "cloud-paper", version.ref = "cloud" }
cloudMinecraftExtras = { group = "cloud.commandframework", name = "cloud-minecraft-extras", version.ref = "cloud" }
[plugins] [plugins]
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
networkTimeout=10000 networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists