diff --git a/Sponge/build.gradle.kts b/Sponge/build.gradle.kts new file mode 100644 index 000000000..84128fd76 --- /dev/null +++ b/Sponge/build.gradle.kts @@ -0,0 +1,81 @@ +import org.spongepowered.gradle.plugin.config.PluginLoaders +import org.spongepowered.plugin.metadata.model.PluginDependency + +plugins { + id("org.spongepowered.gradle.plugin") version "2.0.0" +} + +dependencies { + api(projects.plotSquaredCore) + + compileOnly(libs.worldeditSponge) +} + +sponge { + apiVersion("8.0.0") + license("All Rights Reserved") + loader { + name(PluginLoaders.JAVA_PLAIN) + version("1.0") + } + plugin("sponge") { + displayName("PlotSquared") + entrypoint("com.plotsquared.sponge.SpongePlatform") + description("Easy, yet powerful Plot World generation and management.") + links { + // homepage("https://spongepowered.org") + // source("https://spongepowered.org/source") + // issues("https://spongepowered.org/issues") + } + contributor("Citymonstret") { + description("Author") + } + contributor("Empire92") { + description("Author") + } + contributor("MattBDev") { + description("Author") + } + contributor("dordsor21") { + description("Author") + } + contributor("NotMyFault") { + description("Author") + } + contributor("SirYwell") { + description("Author") + } + dependency("spongeapi") { + loadOrder(PluginDependency.LoadOrder.AFTER) + optional(false) + } +// dependency("${DEPEDENCY}") { +// loadOrder(PluginDependency.LoadOrder.AFTER) +// optional(false) +// } + } +} + +val javaTarget = 16 +java { + sourceCompatibility = JavaVersion.toVersion(javaTarget) + targetCompatibility = JavaVersion.toVersion(javaTarget) + if (JavaVersion.current() < JavaVersion.toVersion(javaTarget)) { + toolchain.languageVersion.set(JavaLanguageVersion.of(javaTarget)) + } +} + +tasks.withType(JavaCompile::class).configureEach { + options.apply { + encoding = "utf-8" // Consistent source file encoding + if (JavaVersion.current().isJava10Compatible) { + release.set(javaTarget) + } + } +} + +// Make sure all tasks which produce archives (jar, sources jar, javadoc jar, etc) produce more consistent output +tasks.withType(AbstractArchiveTask::class).configureEach { + isReproducibleFileOrder = true + isPreserveFileTimestamps = false +} diff --git a/Sponge/src/main/java/com/plotsquared/sponge/SpongePlatform.java b/Sponge/src/main/java/com/plotsquared/sponge/SpongePlatform.java new file mode 100644 index 000000000..bda5038e2 --- /dev/null +++ b/Sponge/src/main/java/com/plotsquared/sponge/SpongePlatform.java @@ -0,0 +1,174 @@ +package com.plotsquared.sponge; + +import com.google.inject.Guice; +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.Stage; +import com.plotsquared.core.PlotPlatform; +import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.configuration.Settings; +import com.plotsquared.core.inject.modules.PlotSquaredModule; +import com.plotsquared.core.plot.world.PlotAreaManager; +import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; +import com.plotsquared.sponge.inject.SpongeModule; +import com.plotsquared.sponge.util.task.SpongeTaskManager; +import com.plotsquared.sponge.util.task.SpongeTimeConverter; +import net.kyori.adventure.identity.Identity; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.LinearComponents; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextDecoration; +import org.apache.logging.log4j.Logger; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.api.Game; +import org.spongepowered.api.Server; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.command.Command; +import org.spongepowered.api.command.CommandResult; +import org.spongepowered.api.command.parameter.Parameter; +import org.spongepowered.api.config.ConfigDir; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.lifecycle.ConstructPluginEvent; +import org.spongepowered.api.event.lifecycle.RegisterCommandEvent; +import org.spongepowered.api.event.lifecycle.StartingEngineEvent; +import org.spongepowered.api.event.lifecycle.StoppingEngineEvent; +import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.builtin.jvm.Plugin; + +import java.io.File; +import java.nio.file.Path; + +/** + * The main class of your Sponge plugin. + * + *

All methods are optional -- some common event registrations are included as a jumping-off point.

+ */ +@Plugin("sponge") +public class SpongePlatform implements PlotPlatform { + + public final PluginContainer container; + private final Logger logger; + private final Game game; + + + @Inject + private PlotAreaManager plotAreaManager; + + @Inject + @ConfigDir(sharedRoot = false) + private Path configDir; + + private int[] version; + private Injector injector; + + @Inject + SpongePlatform(final PluginContainer container, final Logger logger, final Game game) { + this.container = container; + this.logger = logger; + this.game = game; + } + + @Listener + public void onConstructPlugin(final ConstructPluginEvent event) { + // Perform any one-time setup + this.logger.info("Constructing sponge"); + final TaskTime.TimeConverter timeConverter = new SpongeTimeConverter(); + TaskManager.setPlatformImplementation(new SpongeTaskManager(this, timeConverter)); + + final PlotSquared plotSquared = new PlotSquared(this, "Sponge"); + + if (Settings.FAWE_Components.FAWE_HOOK) { + this.logger.info("FAWE Hooks do not work on Sponge. 😞"); + } + + // We create the injector after PlotSquared has been initialized, so that we have access + // to generated instances and settings + this.injector = Guice + .createInjector( + Stage.PRODUCTION, + new PermissionModule(), + new WorldManagerModule(), + new PlotSquaredModule(), + new SpongeModule(this), + new BackupModule() + ); + + } + + @Listener + public void onServerStarting(final StartingEngineEvent event) { + // Any setup per-game instance. This can run multiple times when + // using the integrated (single-player) server. + } + + @Listener + public void onServerStopping(final StoppingEngineEvent event) { + // Any tear down per-game instance. This can run multiple times when + // using the integrated (single-player) server. + } + + @Listener + public void onRegisterCommands(final RegisterCommandEvent event) { + // Register a simple command + // When possible, all commands should be registered within a command register event + final Parameter.Value nameParam = Parameter.string().key("name").build(); + event.register(this.container, Command.builder() + .addParameter(nameParam) + .permission("sponge.command.greet") + .executor(ctx -> { + final String name = ctx.requireOne(nameParam); + ctx.sendMessage(Identity.nil(), LinearComponents.linear( + NamedTextColor.AQUA, + Component.text("Hello "), + Component.text(name, Style.style(TextDecoration.BOLD)), + Component.text("!") + )); + + return CommandResult.success(); + }) + .build(), "greet", "wave"); + } + + @Override + public int[] serverVersion() { + if (this.version == null) { + try { + this.version = new int[3]; + String[] split = Sponge.platform().minecraftVersion().name().split("\\."); + this.version[0] = Integer.parseInt(split[0]); + this.version[1] = Integer.parseInt(split[1]); + if (split.length == 3) { + this.version[2] = Integer.parseInt(split[2]); + } + } catch (Exception e) { + e.printStackTrace(); + return new int[]{1, 16, 5}; + } + } + return this.version; + } + + @Override + public @NonNull String serverImplementation() { + return "Sponge"; //TODO Possibly revaluate the this method name + } + + @Override + public @NonNull File getDirectory() { + return configDir.toFile(); + } + + @Override + public @NonNull File worldContainer() { + return game.gameDirectory().toFile(); //TODO This may be incorrect. Behavior needs verification. + } + + public Logger getLogger() { + return logger; + } + +} diff --git a/Sponge/src/main/java/com/plotsquared/sponge/inject/SpongeModule.java b/Sponge/src/main/java/com/plotsquared/sponge/inject/SpongeModule.java new file mode 100644 index 000000000..2c6386f39 --- /dev/null +++ b/Sponge/src/main/java/com/plotsquared/sponge/inject/SpongeModule.java @@ -0,0 +1,106 @@ +package com.plotsquared.sponge.inject; + +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.assistedinject.FactoryModuleBuilder; +import com.plotsquared.core.PlotPlatform; +import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.configuration.Settings; +import com.plotsquared.core.generator.HybridGen; +import com.plotsquared.core.generator.IndependentPlotGenerator; +import com.plotsquared.core.inject.annotations.ConsoleActor; +import com.plotsquared.core.inject.annotations.DefaultGenerator; +import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory; +import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory; +import com.plotsquared.core.inject.factory.HybridPlotWorldFactory; +import com.plotsquared.core.inject.factory.ProgressSubscriberFactory; +import com.plotsquared.core.plot.world.DefaultPlotAreaManager; +import com.plotsquared.core.plot.world.PlotAreaManager; +import com.plotsquared.core.plot.world.SinglePlotAreaManager; +import com.plotsquared.core.queue.ChunkCoordinator; +import com.plotsquared.core.queue.GlobalBlockQueue; +import com.plotsquared.core.queue.QueueProvider; +import com.plotsquared.core.queue.subscriber.DefaultProgressSubscriber; +import com.plotsquared.core.queue.subscriber.ProgressSubscriber; +import com.plotsquared.core.util.ChunkManager; +import com.plotsquared.core.util.EconHandler; +import com.plotsquared.core.util.InventoryUtil; +import com.plotsquared.core.util.PlayerManager; +import com.plotsquared.core.util.RegionManager; +import com.plotsquared.core.util.SchematicHandler; +import com.plotsquared.core.util.SetupUtils; +import com.plotsquared.core.util.WorldUtil; +import com.plotsquared.sponge.SpongePlatform; +import com.plotsquared.sponge.player.SpongePlayerManager; +import com.plotsquared.sponge.util.SpongeEconHandler; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.service.economy.EconomyService; + +public class SpongeModule extends AbstractModule { + + private final SpongePlatform spongePlatform; + + public SpongeModule(SpongePlatform spongePlatform) { + this.spongePlatform = spongePlatform; + } + + @Override + protected void configure() { + bind(PlayerManager.class).to(SpongePlayerManager.class); + bind(PlotPlatform.class).toInstance(spongePlatform); + bind(SpongePlatform.class).toInstance(spongePlatform); + bind(IndependentPlotGenerator.class).annotatedWith(DefaultGenerator.class).to(HybridGen.class); + // Console actor + @NonNull ConsoleCommandSender console = Sponge.server().getServer().getConsoleSender(); + WorldEditPlugin wePlugin = ((WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit")); + bind(Actor.class).annotatedWith(ConsoleActor.class).toInstance(wePlugin.wrapCommandSender(console)); + bind(InventoryUtil.class).to(BukkitInventoryUtil.class); + bind(SetupUtils.class).to(BukkitSetupUtils.class); + bind(WorldUtil.class).to(BukkitUtil.class); + install(new FactoryModuleBuilder() + .implement(ProgressSubscriber.class, DefaultProgressSubscriber.class) + .build(ProgressSubscriberFactory.class)); + bind(ChunkManager.class).to(BukkitChunkManager.class); + if (PlotSquared.platform().isFaweHooking()) { + bind(SchematicHandler.class).to(FaweSchematicHandler.class); + bind(RegionManager.class).to(FaweRegionManager.class); + } else { + bind(SchematicHandler.class).to(BukkitSchematicHandler.class); + bind(RegionManager.class).to(BukkitRegionManager.class); + } + bind(GlobalBlockQueue.class).toInstance(new GlobalBlockQueue(QueueProvider.of(BukkitQueueCoordinator.class))); + if (Settings.Enabled_Components.WORLDS) { + bind(PlotAreaManager.class).to(SinglePlotAreaManager.class); + try { + bind(SingleWorldListener.class).toInstance(new SingleWorldListener()); + } catch (Exception e) { + e.printStackTrace(); + } + } else { + bind(PlotAreaManager.class).to(DefaultPlotAreaManager.class); + } + install(new FactoryModuleBuilder().build(HybridPlotWorldFactory.class)); + install(new FactoryModuleBuilder() + .implement(ChunkCoordinator.class, BukkitChunkCoordinator.class) + .build(ChunkCoordinatorFactory.class)); + install(new FactoryModuleBuilder().build(ChunkCoordinatorBuilderFactory.class)); + } + + @Provides + @Singleton + @NonNull EconHandler provideEconHandler() { + if (!Settings.Enabled_Components.ECONOMY) { + return EconHandler.nullEconHandler(); + } + SpongeEconHandler economyService = new SpongeEconHandler(); + + if (!economyService.isSupported()) { + spongePlatform.getLogger().warn("Economy is enabled but no plugin is providing an economy service."); + } + + return economyService; + } + +} diff --git a/Sponge/src/main/java/com/plotsquared/sponge/player/SpongeOfflinePlayer.java b/Sponge/src/main/java/com/plotsquared/sponge/player/SpongeOfflinePlayer.java new file mode 100644 index 000000000..b27813ac8 --- /dev/null +++ b/Sponge/src/main/java/com/plotsquared/sponge/player/SpongeOfflinePlayer.java @@ -0,0 +1,37 @@ +package com.plotsquared.sponge.player; + +import com.plotsquared.core.player.OfflinePlotPlayer; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.UUID; + +//TODO Implement +public class SpongeOfflinePlayer implements @Nullable + OfflinePlotPlayer { + + @Override + public boolean hasPermission(@Nullable final String world, @NonNull final String permission) { + return false; + } + + @Override + public boolean hasKeyedPermission(@Nullable final String world, @NonNull final String permission, @NonNull final String key) { + return false; + } + + @Override + public UUID getUUID() { + return null; + } + + @Override + public long getLastPlayed() { + return 0; + } + + @Override + public String getName() { + return null; + } +} diff --git a/Sponge/src/main/java/com/plotsquared/sponge/player/SpongePlayer.java b/Sponge/src/main/java/com/plotsquared/sponge/player/SpongePlayer.java new file mode 100644 index 000000000..53d2f7904 --- /dev/null +++ b/Sponge/src/main/java/com/plotsquared/sponge/player/SpongePlayer.java @@ -0,0 +1,243 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2014 - 2022 IntellectualSites + * + * 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 . + */ +package com.plotsquared.sponge.player; + +import com.plotsquared.core.events.TeleportCause; +import com.plotsquared.core.location.Location; +import com.plotsquared.core.permissions.PermissionHandler; +import com.plotsquared.core.player.ConsolePlayer; +import com.plotsquared.core.player.PlotPlayer; +import com.plotsquared.core.plot.PlotWeather; +import com.plotsquared.core.plot.world.PlotAreaManager; +import com.plotsquared.core.util.EventDispatcher; +import com.plotsquared.sponge.util.SpongeUtil; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.world.gamemode.GameModes; +import com.sk89q.worldedit.world.item.ItemType; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.Component; +import org.checkerframework.checker.index.qual.NonNegative; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.api.ResourceKey; +import org.spongepowered.api.Server; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; +import org.spongepowered.api.registry.RegistryTypes; +import org.spongepowered.api.world.server.ServerLocation; +import org.spongepowered.math.vector.Vector3d; + +import java.util.UUID; + +import static com.sk89q.worldedit.world.gamemode.GameModes.SPECTATOR; + +public class SpongePlayer extends PlotPlayer { + + private static boolean CHECK_EFFECTIVE = true; + public final ServerPlayer player; + private String name; + + /** + *

Please do not use this method. Instead use + * BukkitUtil.getPlayer(Player), as it caches player objects.

+ * + * @param plotAreaManager PlotAreaManager instance + * @param eventDispatcher EventDispatcher instance + * @param player Bukkit player instance + * @param permissionHandler PermissionHandler instance + */ + public SpongePlayer( + final @NonNull PlotAreaManager plotAreaManager, + final @NonNull EventDispatcher eventDispatcher, + final @NonNull ServerPlayer player, + final @NonNull PermissionHandler permissionHandler + ) { + this(plotAreaManager, eventDispatcher, player, false, permissionHandler); + } + + public SpongePlayer( + final @NonNull PlotAreaManager plotAreaManager, + final @NonNull EventDispatcher eventDispatcher, + final @NonNull ServerPlayer player, + final boolean realPlayer, + final @NonNull PermissionHandler permissionHandler + ) { + super(plotAreaManager, eventDispatcher, permissionHandler); + this.player = player; + this.setupPermissionProfile(); + if (realPlayer) { + super.populatePersistentMetaMap(); + } + } + + @Override + public Actor toActor() { + throw new UnsupportedOperationException(); + } + + @Override + public ServerPlayer getPlatformPlayer() { + return this.player; + } + + @NonNull + @Override + public UUID getUUID() { +/* +TODO Fix me + + if (Settings.UUID.OFFLINE) { + if (Settings.UUID.FORCE_LOWERCASE) { + return UUID.nameUUIDFromBytes(("OfflinePlayer:" + + getName().toLowerCase()).getBytes(Charsets.UTF_8)); + } else { + return UUID.nameUUIDFromBytes(("OfflinePlayer:" + + getName()).getBytes(Charsets.UTF_8)); + } + } +*/ + return player.uniqueId(); + } + + @Override + @NonNegative + public long getLastPlayed() { + throw new UnsupportedOperationException("TODO"); + } + + @Override + public boolean canTeleport(final @NonNull Location location) { + throw new UnsupportedOperationException(); + } + + @Override + @NonNegative + public int hasPermissionRange( + final @NonNull String stub, @NonNegative final int range + ) { + throw new UnsupportedOperationException(); + } + + @Override + public void teleport(final @NonNull Location location, final @NonNull TeleportCause cause) { + if (Math.abs(location.getX()) >= 30000000 || Math.abs(location.getZ()) >= 30000000) { + return; + } + final ServerLocation spongeLocation = ServerLocation.of( + ResourceKey.resolve(location.getWorldName()), + location.getX() + 0.5, + location.getY(), + location.getZ() + 0.5 + ); + //TODO has not been tested. + player.setLocationAndRotation(spongeLocation, Vector3d.from(location.getPitch(), location.getYaw(), 0)); + } + + @Override + public String getName() { + if (this.name == null) { + this.name = this.player.name(); + } + return this.player.name(); + } + + @Override + public void setCompassTarget(Location location) { + //Setting compass targets changed since the last Sponge API. + } + + @Override + public Location getLocationFull() { + throw new UnsupportedOperationException(); + } + + @Override + public void setWeather(final @NonNull PlotWeather weather) { + throw new UnsupportedOperationException(); + } + + @Override + public com.sk89q.worldedit.world.gamemode.GameMode getGameMode() { + return GameModes.get(player.gameMode().get().key(RegistryTypes.GAME_MODE).asString()); + } + + @Override + public void setGameMode(final com.sk89q.worldedit.world.gamemode.GameMode gameMode) { + player.gameMode().set(Sponge.game().registry(RegistryTypes.GAME_MODE).value(ResourceKey.resolve(gameMode.getId()))); + } + + @Override + public void setTime(final long time) { + throw new UnsupportedOperationException("Sponge still doesn't support this after more than 4 years of work on API 8."); + } + + @Override + public boolean getFlight() { + return player.canFly().get(); + } + + @Override + public void setFlight(boolean fly) { + this.player.canFly().set(fly); + } + + @Override + public void playMusic(final @NonNull Location location, final @NonNull ItemType id) { + throw new UnsupportedOperationException(); + } + + @Override + public void kick(final String message) { + this.player.kick(Component.text(message)); + } + + @Override + public void stopSpectating() { + if (getGameMode() == SPECTATOR) { + this.player.spectatorTarget().set(null); + } + } + + @Override + public boolean isBanned() { + throw new UnsupportedOperationException(); + } + + @Override + public @NonNull Audience getAudience() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean canSee(final PlotPlayer other) { + if (other instanceof ConsolePlayer) { + return true; + } else { + return this.player.canSee(null); //TODO Fix Me? + } + } + +} diff --git a/Sponge/src/main/java/com/plotsquared/sponge/player/SpongePlayerManager.java b/Sponge/src/main/java/com/plotsquared/sponge/player/SpongePlayerManager.java new file mode 100644 index 000000000..ac8011685 --- /dev/null +++ b/Sponge/src/main/java/com/plotsquared/sponge/player/SpongePlayerManager.java @@ -0,0 +1,86 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2014 - 2022 IntellectualSites + * + * 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 . + */ +package com.plotsquared.sponge.player; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import com.plotsquared.core.permissions.PermissionHandler; +import com.plotsquared.core.plot.world.PlotAreaManager; +import com.plotsquared.core.util.EventDispatcher; +import com.plotsquared.core.util.PlayerManager; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.Server; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.entity.living.player.server.ServerPlayer; +import org.spongepowered.api.user.UserManager; + +import java.util.UUID; + +@Singleton +public class SpongePlayerManager extends PlayerManager { + + private final PlotAreaManager plotAreaManager; + private final EventDispatcher eventDispatcher; + private final PermissionHandler permissionHandler; + private final UserManager userManager; + + @Inject + public SpongePlayerManager( + final @NonNull PlotAreaManager plotAreaManager, + final @NonNull EventDispatcher eventDispatcher, + final @NonNull PermissionHandler permissionHandler + ) { + this.plotAreaManager = plotAreaManager; + this.eventDispatcher = eventDispatcher; + this.permissionHandler = permissionHandler; + userManager = Sponge.game().server().userManager(); + } + + @NonNull + @Override + public SpongePlayer getPlayer(final @NonNull ServerPlayer object) { + throw new UnsupportedOperationException(); + } + + @Override + public @NonNull SpongePlayer createPlayer(final @NonNull UUID uuid) { + throw new UnsupportedOperationException(); + } + + @Nullable + @Override + public SpongeOfflinePlayer getOfflinePlayer(final @Nullable UUID uuid) { + throw new UnsupportedOperationException(); + } + + @NonNull + @Override + public SpongeOfflinePlayer getOfflinePlayer(final @NonNull String username) { + throw new UnsupportedOperationException(); + } + +} diff --git a/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeEconHandler.java b/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeEconHandler.java new file mode 100644 index 000000000..ea115691f --- /dev/null +++ b/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeEconHandler.java @@ -0,0 +1,71 @@ +package com.plotsquared.sponge.util; + +import com.google.inject.Singleton; +import com.plotsquared.core.player.OfflinePlotPlayer; +import com.plotsquared.core.player.PlotPlayer; +import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.util.EconHandler; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.service.economy.Currency; +import org.spongepowered.api.service.economy.EconomyService; +import org.spongepowered.api.service.economy.account.UniqueAccount; + +import java.util.Optional; + + +@Singleton +public class SpongeEconHandler extends EconHandler { + + private final Optional economyService; //TODO maybe don't store an optional? + + public SpongeEconHandler() { + economyService = Sponge.serviceProvider().provide(EconomyService.class); + } + + @Override + public boolean init() { + return Sponge.serviceProvider().provide(EconomyService.class).isPresent(); + } + + @Override + public double getBalance(final PlotPlayer player) { + if(economyService.isPresent()) { + final Optional account = economyService.get().findOrCreateAccount(player.getUUID()); + return account + .map(uniqueAccount -> uniqueAccount.balance(economyService.get().defaultCurrency()).doubleValue()) + .orElse(0.0); + } + return 0; + } + + @Override + public void withdrawMoney(final PlotPlayer player, final double amount) { + + } + + @Override + public void depositMoney(final PlotPlayer player, final double amount) { + + } + + @Override + public void depositMoney(final OfflinePlotPlayer player, final double amount) { + } + + @Override + public boolean isEnabled(final PlotArea plotArea) { + return false; + } + + @Override + public @NonNull String format(final double balance) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isSupported() { + return Sponge.serviceProvider().provide(EconomyService.class).isPresent(); + } + +} diff --git a/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeUtil.java b/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeUtil.java new file mode 100644 index 000000000..f0eb42926 --- /dev/null +++ b/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeUtil.java @@ -0,0 +1,7 @@ +package com.plotsquared.sponge.util; + +import com.plotsquared.core.location.Location; +import com.plotsquared.core.util.WorldUtil; + +public class SpongeUtil extends WorldUtil { +} diff --git a/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeWorld.java b/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeWorld.java new file mode 100644 index 000000000..c453e6a4a --- /dev/null +++ b/Sponge/src/main/java/com/plotsquared/sponge/util/SpongeWorld.java @@ -0,0 +1,25 @@ +package com.plotsquared.sponge.util; + +import com.plotsquared.core.location.World; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.api.world.server.ServerWorld; + +public class SpongeWorld implements World { + + private final ServerWorld world; + + private SpongeWorld(final ServerWorld world) { + this.world = world; + } + + @Override + public @NonNull ServerWorld getPlatformWorld() { + return this.world; + } + + @Override + public @NonNull String getName() { + return this.world.key().asString(); + } + +} diff --git a/Sponge/src/main/java/com/plotsquared/sponge/util/task/SpongeTaskManager.java b/Sponge/src/main/java/com/plotsquared/sponge/util/task/SpongeTaskManager.java new file mode 100644 index 000000000..cd7537e2d --- /dev/null +++ b/Sponge/src/main/java/com/plotsquared/sponge/util/task/SpongeTaskManager.java @@ -0,0 +1,69 @@ +package com.plotsquared.sponge.util.task; + +import com.plotsquared.core.util.task.PlotSquaredTask; +import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.util.task.TaskTime; +import com.plotsquared.sponge.SpongePlatform; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.scheduler.Task; +import org.spongepowered.api.util.Ticks; + +import java.util.concurrent.Callable; +import java.util.concurrent.Future; + +public class SpongeTaskManager extends TaskManager { + + private final SpongePlatform spongeMain; + private final TaskTime.TimeConverter timeConverter; + + public SpongeTaskManager(SpongePlatform spongeMain, TaskTime.TimeConverter timeConverter) { + this.spongeMain = spongeMain; + this.timeConverter = timeConverter; + } + + @Override + public T sync(final @NonNull Callable function, final int timeout) throws Exception { + return null; //TODO + } + + @Override + public Future callMethodSync(final @NonNull Callable method) { + return null; //TODO + } + + @Override + public PlotSquaredTask taskRepeat(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { + return null; //TODO + } + + @Override + public PlotSquaredTask taskRepeatAsync(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { + //TODO input the current tick delay and interval using the Sponge Tick API. + Task task = + Task.builder().delay(Ticks.zero()).interval(Ticks.zero()).plugin(spongeMain.container).execute(runnable).build(); + Sponge.asyncScheduler().submit(task); + return null; + } + + @Override + public void taskAsync(@NonNull final Runnable runnable) { + //TODO + } + + @Override + public void task(@NonNull final Runnable runnable) { + Task.builder().execute(runnable).plugin(spongeMain.container); + } + + @Override + public void taskLater(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { + //TODO + } + + @Override + public void taskLaterAsync(@NonNull final Runnable runnable, @NonNull final TaskTime taskTime) { + //TODO + } + +} diff --git a/Sponge/src/main/java/com/plotsquared/sponge/util/task/SpongeTimeConverter.java b/Sponge/src/main/java/com/plotsquared/sponge/util/task/SpongeTimeConverter.java new file mode 100644 index 000000000..2032c3126 --- /dev/null +++ b/Sponge/src/main/java/com/plotsquared/sponge/util/task/SpongeTimeConverter.java @@ -0,0 +1,20 @@ +package com.plotsquared.sponge.util.task; + +import com.plotsquared.core.util.task.TaskTime; +import org.checkerframework.checker.index.qual.NonNegative; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.util.Ticks; + +public class SpongeTimeConverter implements TaskTime.TimeConverter { + + @Override + public @NonNegative long msToTicks(@NonNegative final long ms) { + return 0; // TODO + } + + @Override + public @NonNegative long ticksToMs(@NonNegative final long ticks) { + return 0; // TODO + } + +} diff --git a/build.gradle.kts b/build.gradle.kts index d2305ae38..3cd81b278 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -26,6 +26,7 @@ allprojects { repositories { mavenCentral() + mavenLocal() maven { name = "Sonatype OSS" diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4d121e624..1b4d002e9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,7 +17,7 @@ adventure-text-minimessage = "4.1.0-SNAPSHOT" adventure-platform-bukkit = "4.0.1" # Plugins -worldedit = "7.2.8" +worldedit = "7.2.9-SNAPSHOT" fawe = "2.0.0" vault = "1.7.1" placeholderapi = "2.11.1" @@ -66,6 +66,7 @@ adventurePlatformBukkit = { group = "net.kyori", name = "adventure-platform-bukk # Plugins worldeditCore = { group = "com.sk89q.worldedit", name = "worldedit-core", version.ref = "worldedit" } worldeditBukkit = { group = "com.sk89q.worldedit", name = "worldedit-bukkit", version.ref = "worldedit" } +worldeditSponge = { group = "com.sk89q.worldedit", name = "worldedit-sponge", version.ref = "worldedit" } fastasyncworldeditBukkit = { group = "com.fastasyncworldedit", name = "FastAsyncWorldEdit-Bukkit", version.ref = "fawe" } fastasyncworldeditCore = { group = "com.fastasyncworldedit", name = "FastAsyncWorldEdit-Core", version.ref = "fawe" } vault = { group = "com.github.MilkBowl", name = "VaultAPI", version.ref = "vault" } diff --git a/settings.gradle.kts b/settings.gradle.kts index c6cbce9df..10c4930c2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,9 +1,10 @@ rootProject.name = "PlotSquared" -include("Core", "Bukkit") +include("Core", "Bukkit", "Sponge") project(":Core").name = "PlotSquared-Core" project(":Bukkit").name = "PlotSquared-Bukkit" +project(":Sponge").name = "PlotSquared-Sponge" enableFeaturePreview("VERSION_CATALOGS") enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")