mirror of
https://github.com/IntellectualSites/PlotSquared.git
synced 2024-11-22 13:16:45 +01:00
Merge pull request #2897 from IntellectualSites/features/v6/services
This commit is contained in:
commit
667c7b07b6
@ -126,6 +126,7 @@ shadowJar {
|
||||
include(dependency('org.slf4j:slf4j-api'))
|
||||
include(dependency('javax.inject:javax.inject:1'))
|
||||
include(dependency('aopalliance:aopalliance:1.0'))
|
||||
include(dependency('com.intellectualsites:Pipeline:1.4.0-SNAPSHOT'))
|
||||
}
|
||||
|
||||
relocate('net.kyori.adventure', 'com.plotsquared.core.configuration.adventure')
|
||||
|
@ -23,6 +23,7 @@ dependencies {
|
||||
compile group: 'aopalliance', name: 'aopalliance', version: '1.0'
|
||||
// logging
|
||||
implementation("org.apache.logging.log4j:log4j-slf4j-impl:2.8.1")
|
||||
implementation('com.intellectualsites:Pipeline:1.4.0-SNAPSHOT')
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
|
@ -28,6 +28,7 @@ package com.plotsquared.core;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import com.intellectualsites.services.ServicePipeline;
|
||||
import com.plotsquared.core.backup.BackupManager;
|
||||
import com.plotsquared.core.configuration.caption.LocaleHolder;
|
||||
import com.plotsquared.core.generator.GeneratorWrapper;
|
||||
@ -269,4 +270,13 @@ public interface PlotPlatform<P> extends LocaleHolder {
|
||||
return getInjector().getInstance(PermissionHandler.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link ServicePipeline} implementation
|
||||
*
|
||||
* @return Service pipeline
|
||||
*/
|
||||
@Nonnull default ServicePipeline getServicePipeline() {
|
||||
return getInjector().getInstance(ServicePipeline.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,8 +25,9 @@
|
||||
*/
|
||||
package com.plotsquared.core.command;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.inject.Inject;
|
||||
import com.intellectualsites.services.ServicePipeline;
|
||||
import com.plotsquared.core.PlotSquared;
|
||||
import com.plotsquared.core.configuration.Settings;
|
||||
import com.plotsquared.core.configuration.caption.TranslatableCaption;
|
||||
@ -34,7 +35,6 @@ import com.plotsquared.core.database.DBFunc;
|
||||
import com.plotsquared.core.events.PlayerAutoPlotEvent;
|
||||
import com.plotsquared.core.events.PlotAutoMergeEvent;
|
||||
import com.plotsquared.core.events.Result;
|
||||
import com.plotsquared.core.events.TeleportCause;
|
||||
import com.plotsquared.core.permissions.Permission;
|
||||
import com.plotsquared.core.permissions.PermissionHandler;
|
||||
import com.plotsquared.core.player.MetaDataAccess;
|
||||
@ -42,9 +42,8 @@ import com.plotsquared.core.player.PlayerMetaDataKeys;
|
||||
import com.plotsquared.core.player.PlotPlayer;
|
||||
import com.plotsquared.core.plot.Plot;
|
||||
import com.plotsquared.core.plot.PlotArea;
|
||||
import com.plotsquared.core.plot.PlotAreaType;
|
||||
import com.plotsquared.core.plot.PlotId;
|
||||
import com.plotsquared.core.plot.world.PlotAreaManager;
|
||||
import com.plotsquared.core.services.plots.AutoService;
|
||||
import com.plotsquared.core.util.EconHandler;
|
||||
import com.plotsquared.core.util.EventDispatcher;
|
||||
import com.plotsquared.core.util.Expression;
|
||||
@ -56,8 +55,10 @@ import net.kyori.adventure.text.minimessage.Template;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@CommandDeclaration(command = "auto",
|
||||
permission = "plots.auto",
|
||||
@ -70,13 +71,23 @@ public class Auto extends SubCommand {
|
||||
private final PlotAreaManager plotAreaManager;
|
||||
private final EventDispatcher eventDispatcher;
|
||||
private final EconHandler econHandler;
|
||||
private final ServicePipeline servicePipeline;
|
||||
|
||||
@Inject public Auto(@Nonnull final PlotAreaManager plotAreaManager,
|
||||
@Nonnull final EventDispatcher eventDispatcher,
|
||||
@Nullable final EconHandler econHandler) {
|
||||
@Nullable final EconHandler econHandler,
|
||||
@Nonnull final ServicePipeline servicePipeline) {
|
||||
this.plotAreaManager = plotAreaManager;
|
||||
this.eventDispatcher = eventDispatcher;
|
||||
this.econHandler = econHandler;
|
||||
this.servicePipeline = servicePipeline;
|
||||
this.servicePipeline.registerServiceType(TypeToken.of(AutoService.class), new AutoService.DefaultAutoService());
|
||||
final AutoService.MultiPlotService multiPlotService = new AutoService.MultiPlotService();
|
||||
this.servicePipeline.registerServiceImplementation(AutoService.class, multiPlotService,
|
||||
Collections.singletonList(multiPlotService));
|
||||
final AutoService.SinglePlotService singlePlotService = new AutoService.SinglePlotService();
|
||||
this.servicePipeline.registerServiceImplementation(AutoService.class, singlePlotService,
|
||||
Collections.singletonList(singlePlotService));
|
||||
}
|
||||
|
||||
public static boolean checkAllowedPlots(PlotPlayer player, PlotArea plotarea,
|
||||
@ -122,62 +133,32 @@ public class Auto extends SubCommand {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teleport the player home, or claim a new plot
|
||||
*
|
||||
* @param player player
|
||||
* @param area plot area
|
||||
* @param start start id
|
||||
* @param schematic schematic
|
||||
*/
|
||||
public static void homeOrAuto(final PlotPlayer player, final PlotArea area, PlotId start,
|
||||
final String schematic) {
|
||||
Set<Plot> plots = player.getPlots();
|
||||
if (!plots.isEmpty()) {
|
||||
plots.iterator().next().teleportPlayer(player, TeleportCause.COMMAND, result -> {
|
||||
});
|
||||
} else {
|
||||
autoClaimSafe(player, area, start, schematic);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Claim a new plot for a player
|
||||
*
|
||||
* @param player player
|
||||
* @param area plot area
|
||||
* @param start start id
|
||||
* @param schematic schematic
|
||||
*/
|
||||
public static void autoClaimSafe(final PlotPlayer<?> player, final PlotArea area, PlotId start,
|
||||
final String schematic) {
|
||||
private void claimSingle(@Nonnull final PlotPlayer<?> player, @Nonnull final Plot plot,
|
||||
@Nonnull final PlotArea plotArea, @Nullable final String schematic) {
|
||||
try (final MetaDataAccess<Boolean> metaDataAccess =
|
||||
player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_AUTO)) {
|
||||
metaDataAccess.set(true);
|
||||
}
|
||||
autoClaimFromDatabase(player, area, start, new RunnableVal<Plot>() {
|
||||
plot.setOwnerAbs(player.getUUID());
|
||||
|
||||
final RunnableVal<Plot> runnableVal = new RunnableVal<Plot>() {
|
||||
{
|
||||
this.value = plot;
|
||||
}
|
||||
|
||||
@Override public void run(final Plot plot) {
|
||||
try {
|
||||
TaskManager.getPlatformImplementation().sync(new AutoClaimFinishTask(player, plot, area, schematic,
|
||||
TaskManager.getPlatformImplementation().sync(
|
||||
new AutoClaimFinishTask(player, plot, plotArea, schematic,
|
||||
PlotSquared.get().getEventDispatcher()));
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
DBFunc.createPlotSafe(plot, runnableVal, () -> claimSingle(player, plot, plotArea, schematic));
|
||||
|
||||
public static void autoClaimFromDatabase(final PlotPlayer player, final PlotArea area,
|
||||
PlotId start, final RunnableVal<Plot> whenDone) {
|
||||
final Plot plot = area.getNextFreePlot(player, start);
|
||||
if (plot == null) {
|
||||
whenDone.run(null);
|
||||
return;
|
||||
}
|
||||
whenDone.value = plot;
|
||||
plot.setOwnerAbs(player.getUUID());
|
||||
DBFunc.createPlotSafe(plot, whenDone,
|
||||
() -> autoClaimFromDatabase(player, area, plot.getId(), whenDone));
|
||||
}
|
||||
|
||||
@Override public boolean onCommand(final PlotPlayer<?> player, String[] args) {
|
||||
@ -312,34 +293,24 @@ public class Auto extends SubCommand {
|
||||
);
|
||||
}
|
||||
}
|
||||
// TODO handle type 2 (partial) the same as normal worlds!
|
||||
if (size_x == 1 && size_z == 1) {
|
||||
autoClaimSafe(player, plotarea, null, schematic);
|
||||
return true;
|
||||
} else {
|
||||
if (plotarea.getType() == PlotAreaType.PARTIAL) {
|
||||
|
||||
final List<Plot> plots = this.servicePipeline
|
||||
.pump(new AutoService.AutoQuery(player, null, size_x, size_z, plotarea))
|
||||
.through(AutoService.class)
|
||||
.getResult();
|
||||
|
||||
if (plots.isEmpty()) {
|
||||
player.sendMessage(TranslatableCaption.of("errors.no_free_plots"));
|
||||
return false;
|
||||
} else if (plots.size() == 1) {
|
||||
this.claimSingle(player, plots.get(0), plotarea, schematic);
|
||||
} else {
|
||||
final Iterator<Plot> plotIterator = plots.iterator();
|
||||
while (plotIterator.hasNext()) {
|
||||
plotIterator.next().claim(player, !plotIterator.hasNext(), null);
|
||||
}
|
||||
while (true) {
|
||||
PlotId start = plotarea.getMeta("lastPlot", PlotId.of(0, 0)).getNextId();
|
||||
PlotId end = PlotId.of(start.getX() + size_x - 1, start.getY() + size_z - 1);
|
||||
if (plotarea.canClaim(player, start, end)) {
|
||||
plotarea.setMeta("lastPlot", start);
|
||||
|
||||
for (final PlotId plotId : PlotId.PlotRangeIterator.range(start, end)) {
|
||||
final Plot plot = plotarea.getPlot(plotId);
|
||||
if (plot == null) {
|
||||
return false;
|
||||
}
|
||||
plot.claim(player, plotId.equals(end), null);
|
||||
}
|
||||
|
||||
final List<PlotId> plotIds = Lists.newArrayList((Iterable<? extends PlotId>)
|
||||
PlotId.PlotRangeIterator.range(start, end));
|
||||
final PlotId pos1 = plotIds.get(0);
|
||||
final PlotAutoMergeEvent mergeEvent = this.eventDispatcher
|
||||
.callAutoMerge(plotarea.getPlotAbs(pos1), plotIds);
|
||||
final PlotAutoMergeEvent mergeEvent = this.eventDispatcher.callAutoMerge(plots.get(0),
|
||||
plots.stream().map(Plot::getId).collect(Collectors.toList()));
|
||||
if (!force && mergeEvent.getEventResult() == Result.DENY) {
|
||||
player.sendMessage(
|
||||
TranslatableCaption.of("events.event_denied"),
|
||||
@ -347,14 +318,8 @@ public class Auto extends SubCommand {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (!plotarea.mergePlots(mergeEvent.getPlots(), true)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
plotarea.setMeta("lastPlot", start);
|
||||
return plotarea.mergePlots(mergeEvent.getPlots(), true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
package com.plotsquared.core.inject.modules;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.intellectualsites.services.ServicePipeline;
|
||||
import com.plotsquared.core.PlotSquared;
|
||||
import com.plotsquared.core.configuration.file.YamlConfiguration;
|
||||
import com.plotsquared.core.inject.annotations.BackgroundPipeline;
|
||||
@ -44,6 +45,7 @@ public class PlotSquaredModule extends AbstractModule {
|
||||
|
||||
@Override protected void configure() {
|
||||
final PlotSquared plotSquared = PlotSquared.get();
|
||||
bind(ServicePipeline.class).toInstance(ServicePipeline.builder().build());
|
||||
bind(YamlConfiguration.class).annotatedWith(WorldConfig.class).toInstance(plotSquared.getWorldConfiguration());
|
||||
bind(File.class).annotatedWith(WorldFile.class).toInstance(plotSquared.getWorldsFile());
|
||||
bind(File.class).annotatedWith(ConfigFile.class).toInstance(plotSquared.getConfigFile());
|
||||
|
@ -83,6 +83,7 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@ -911,31 +912,38 @@ public abstract class PlotArea {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canClaim(@Nullable final PlotPlayer player, @Nonnull final PlotId pos1,
|
||||
@Nullable public List<Plot> canClaim(@Nullable final PlotPlayer player, @Nonnull final PlotId pos1,
|
||||
@Nonnull final PlotId pos2) {
|
||||
if (pos1.getX() == pos2.getX() && pos1.getY() == pos2.getY()) {
|
||||
if (getOwnedPlot(pos1) != null) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
final Plot plot = getPlotAbs(pos1);
|
||||
if (plot == null) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
return plot.canClaim(player);
|
||||
if (plot.canClaim(player)) {
|
||||
return Collections.singletonList(plot);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
final List<Plot> plots = new LinkedList<>();
|
||||
for (int x = pos1.getX(); x <= pos2.getX(); x++) {
|
||||
for (int y = pos1.getY(); y <= pos2.getY(); y++) {
|
||||
final PlotId id = PlotId.of(x, y);
|
||||
final Plot plot = getPlotAbs(id);
|
||||
if (plot == null) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
if (!plot.canClaim(player)) {
|
||||
return false;
|
||||
return null;
|
||||
} else {
|
||||
plots.add(plot);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return plots;
|
||||
}
|
||||
|
||||
public boolean removePlot(@Nonnull final PlotId id) {
|
||||
|
@ -0,0 +1,163 @@
|
||||
package com.plotsquared.core.services.plots;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.intellectualsites.services.types.Service;
|
||||
import com.plotsquared.core.player.PlotPlayer;
|
||||
import com.plotsquared.core.plot.Plot;
|
||||
import com.plotsquared.core.plot.PlotArea;
|
||||
import com.plotsquared.core.plot.PlotAreaType;
|
||||
import com.plotsquared.core.plot.PlotId;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public interface AutoService extends Service<AutoService.AutoQuery, List<Plot>> {
|
||||
|
||||
Cache<PlotId, Plot> plotCandidateCache = CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(20, TimeUnit.SECONDS).build();
|
||||
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(@Nonnull final PlotPlayer<?> player, @Nullable final PlotId startId,
|
||||
final int sizeX, final int sizeZ, @Nonnull final 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
|
||||
*/
|
||||
@Nonnull public PlotPlayer<?> getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plot ID to start searching from
|
||||
*
|
||||
* @return Start ID
|
||||
*/
|
||||
@Nullable public 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
|
||||
*/
|
||||
@Nonnull public PlotArea getPlotArea() {
|
||||
return this.plotArea;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
final class DefaultAutoService implements AutoService {
|
||||
|
||||
@Override public List<Plot> handle(@Nonnull final AutoQuery autoQuery) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
final class SinglePlotService implements AutoService, Predicate<AutoQuery> {
|
||||
|
||||
@Nullable @Override public List<Plot> handle(@Nonnull AutoQuery autoQuery) {
|
||||
Plot plot;
|
||||
do {
|
||||
synchronized (plotLock) {
|
||||
plot = autoQuery.getPlotArea().getNextFreePlot(autoQuery.getPlayer(), autoQuery.getStartId());
|
||||
if (plot != null && plotCandidateCache.getIfPresent(plot.getId()) == null) {
|
||||
plotCandidateCache.put(plot.getId(), plot);
|
||||
return Collections.singletonList(plot);
|
||||
}
|
||||
}
|
||||
} while (plot != null);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override public boolean test(@Nonnull final AutoQuery autoQuery) {
|
||||
return autoQuery.sizeX == 1 && autoQuery.sizeZ == 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
final class MultiPlotService implements AutoService, Predicate<AutoQuery> {
|
||||
|
||||
@Override public List<Plot> handle(@Nonnull final AutoQuery autoQuery) {
|
||||
/* TODO: Add timeout? */
|
||||
outer: while (true) {
|
||||
synchronized (plotLock) {
|
||||
final PlotId start =
|
||||
autoQuery.getPlotArea().getMeta("lastPlot", PlotId.of(0, 0)).getNextId();
|
||||
final PlotId end = PlotId.of(start.getX() + autoQuery.getSizeX() - 1,
|
||||
start.getY() + autoQuery.getSizeZ() - 1);
|
||||
final List<Plot> plots =
|
||||
autoQuery.getPlotArea().canClaim(autoQuery.getPlayer(), start, end);
|
||||
if (plots != null && !plots.isEmpty()) {
|
||||
autoQuery.getPlotArea().setMeta("lastPlot", start);
|
||||
for (final Plot plot : plots) {
|
||||
if (plotCandidateCache.getIfPresent(plot.getId()) != null) {
|
||||
continue outer;
|
||||
}
|
||||
plotCandidateCache.put(plot.getId(), plot);
|
||||
}
|
||||
return plots;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean test(@Nonnull final AutoQuery autoQuery) {
|
||||
return autoQuery.getPlotArea().getType() != PlotAreaType.PARTIAL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user