Merge pull request #2897 from IntellectualSites/features/v6/services

This commit is contained in:
Alexander Söderberg 2020-08-21 23:03:29 +02:00 committed by GitHub
commit 667c7b07b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 248 additions and 98 deletions

View File

@ -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')

View File

@ -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

View File

@ -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);
}
}

View File

@ -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,
PlotSquared.get().getEventDispatcher()));
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,49 +293,33 @@ 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;
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 {
if (plotarea.getType() == PlotAreaType.PARTIAL) {
player.sendMessage(TranslatableCaption.of("errors.no_free_plots"));
final Iterator<Plot> plotIterator = plots.iterator();
while (plotIterator.hasNext()) {
plotIterator.next().claim(player, !plotIterator.hasNext(), null);
}
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"),
Template.of("value", "Auto merge")
);
return false;
}
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);
if (!force && mergeEvent.getEventResult() == Result.DENY) {
player.sendMessage(
TranslatableCaption.of("events.event_denied"),
Template.of("value", "Auto merge")
);
return false;
}
if (!plotarea.mergePlots(mergeEvent.getPlots(), true)) {
return false;
}
break;
}
plotarea.setMeta("lastPlot", start);
}
return true;
return plotarea.mergePlots(mergeEvent.getPlots(), true);
}
return true;
}
}

View File

@ -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());

View File

@ -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;
}
if (plot.canClaim(player)) {
return Collections.singletonList(plot);
} else {
return null;
}
return plot.canClaim(player);
}
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) {

View File

@ -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;
}
}
}