mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-09-27 22:17:32 +02:00
Sponge API 8 port (#2119)
* Initial commit for Sponge API 8 port * Change Sponge PAL version to include -sponge version suffix * Comment out Nucleus w/ needs a update in ExtensionRegister * Fix error with ArtifactVersion (from org.apache.maven) being relocated * Correct todos related to getting values from ResourceKeys * Cleanup sponge buildscript a bit * Remove sout * Update Extension-Sponge-Economy to 8.0.0-R0.3 * Convert to Sponge's new preferred way to load in jar resources * Convert SpongeMessageBuilder and VelocityMessageBuilder into AdventureMessageBuilder * Add back the command * Update bStats to 3.0.0, re-enable bStats for Sponge * Implement gamemode change mixin * Remove unused import * Update SpongeGMChangeListener's error logging as suggested Co-authored-by: Aurora Lahtela <24460436+AuroraLS3@users.noreply.github.com> * PAL 5.1.0 * Add a check in SpongeCommand to update the ErrorLogger and Subcommand if the PlanSpongeComponent changes * Combine try-with-resources in SpongePlanFiles#asStringResource Co-authored-by: Aurora Lahtela <24460436+AuroraLS3@users.noreply.github.com>
This commit is contained in:
parent
5066806752
commit
bab0f273a2
@ -62,12 +62,12 @@ subprojects {
|
||||
ext {
|
||||
daggerVersion = "2.42"
|
||||
|
||||
palVersion = "5.0.3"
|
||||
palVersion = "5.1.0"
|
||||
|
||||
bukkitVersion = "1.13.2-R0.1-SNAPSHOT"
|
||||
spigotVersion = "1.13.2-R0.1-SNAPSHOT"
|
||||
paperVersion = "1.13.2-R0.1-SNAPSHOT"
|
||||
spongeVersion = "7.4.0"
|
||||
spongeVersion = "8.1.0"
|
||||
nukkitVersion = "1.0-SNAPSHOT"
|
||||
bungeeVersion = "1.16-R0.4"
|
||||
velocityVersion = "3.0.0-SNAPSHOT"
|
||||
@ -84,7 +84,7 @@ subprojects {
|
||||
gsonVersion = "2.9.0"
|
||||
dependencyDownloadVersion = "1.2.1"
|
||||
|
||||
bstatsVersion = "2.2.1"
|
||||
bstatsVersion = "3.0.0"
|
||||
placeholderapiVersion = "2.11.1"
|
||||
nkPlaceholderapiVersion = "1.4-SNAPSHOT"
|
||||
|
||||
|
@ -42,6 +42,7 @@ dependencies {
|
||||
implementation "org.slf4j:slf4j-api:$slf4jVersion"
|
||||
implementation "com.maxmind.geoip2:geoip2:$geoIpVersion"
|
||||
implementation "com.google.code.gson:gson:$gsonVersion"
|
||||
compileOnly "net.kyori:adventure-api:4.9.3"
|
||||
|
||||
implementation("dev.vankka:dependencydownload-runtime:$dependencyDownloadVersion") {
|
||||
// Effectively disables relocating
|
||||
|
@ -150,8 +150,18 @@ public class PlanSystem implements SubSystem {
|
||||
return webServerSystem.getAddresses().getMainAddress().orElse(webServerSystem.getAddresses().getFallbackLocalhostAddress());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
/**
|
||||
* Enables only the systems that are required for {@link com.djrapitops.plan.commands.PlanCommand}.
|
||||
* @see #enableOtherThanCommands()
|
||||
*/
|
||||
public void enableForCommands() {
|
||||
enableSystems(configSystem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the rest of the systems that are not enabled in {@link #enableForCommands()}.
|
||||
*/
|
||||
public void enableOtherThanCommands() {
|
||||
extensionService.register();
|
||||
resolverService.register();
|
||||
resourceService.register();
|
||||
@ -162,7 +172,6 @@ public class PlanSystem implements SubSystem {
|
||||
|
||||
enableSystems(
|
||||
files,
|
||||
configSystem,
|
||||
localeSystem,
|
||||
versionChecker,
|
||||
databaseSystem,
|
||||
@ -196,6 +205,12 @@ public class PlanSystem implements SubSystem {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable() {
|
||||
enableForCommands();
|
||||
enableOtherThanCommands();
|
||||
}
|
||||
|
||||
private void enableSystems(SubSystem... systems) {
|
||||
for (SubSystem system : systems) {
|
||||
system.enable();
|
||||
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.djrapitops.plan.commands.use;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
@ -24,16 +25,21 @@ import org.apache.commons.text.TextStringBuilder;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class VelocityMessageBuilder implements MessageBuilder {
|
||||
/**
|
||||
* Shared Adventure {@link MessageBuilder} shared by Velocity and Sponge.
|
||||
*/
|
||||
public class AdventureMessageBuilder implements MessageBuilder {
|
||||
|
||||
private final VelocityCMDSender sender;
|
||||
private final CMDSender sender;
|
||||
private final Audience audience;
|
||||
private final TextComponent.Builder builder;
|
||||
|
||||
// Store reference to previous component to properly add hover & click events
|
||||
private Component previousComponent;
|
||||
|
||||
public VelocityMessageBuilder(VelocityCMDSender sender) {
|
||||
AdventureMessageBuilder(CMDSender sender, Audience audience) {
|
||||
this.sender = sender;
|
||||
this.audience = audience;
|
||||
builder = Component.text();
|
||||
}
|
||||
|
||||
@ -112,6 +118,6 @@ public class VelocityMessageBuilder implements MessageBuilder {
|
||||
if (previousComponent != null) {
|
||||
builder.append(previousComponent);
|
||||
}
|
||||
sender.commandSource.sendMessage(builder.build());
|
||||
audience.sendMessage(builder.build());
|
||||
}
|
||||
}
|
@ -40,7 +40,7 @@ dependencies {
|
||||
implementation 'com.djrapitops:Extension-Quests:4.0.5-R0.1'
|
||||
implementation 'com.djrapitops:Extension-React:6.651-R0.1'
|
||||
implementation 'com.djrapitops:Extension-RedProtect:7.7.3-R0.1'
|
||||
implementation 'com.djrapitops:Extension-Sponge-Economy:7.1.0-R0.3'
|
||||
implementation 'com.djrapitops:Extension-Sponge-Economy:8.0.0-R0.3'
|
||||
implementation 'com.djrapitops:Extension-SuperbVote:0.5.4-R0.1'
|
||||
implementation 'com.djrapitops:Extension-Tebex:R1.3'
|
||||
implementation 'com.djrapitops:Extension-Towny:0.96.7.4-R0.2'
|
||||
|
@ -75,7 +75,7 @@ public class ExtensionRegister {
|
||||
register(new FloodgateExtensionFactory(), FloodgateExtensionFactory::createExtension, FloodgateExtensionFactory::registerListener);
|
||||
register(new GriefDefenderExtensionFactory(), GriefDefenderExtensionFactory::createExtension);
|
||||
register(new GriefPreventionExtensionFactory(), GriefPreventionExtensionFactory::createExtension);
|
||||
register(new GriefPreventionSpongeExtensionFactory(), GriefPreventionSpongeExtensionFactory::createExtension);
|
||||
//register(new GriefPreventionSpongeExtensionFactory(), GriefPreventionSpongeExtensionFactory::createExtension); // TODO: update for Sponge API 8
|
||||
register(new HeroesExtensionFactory(), HeroesExtensionFactory::createExtension);
|
||||
register(new KingdomsXExtensionFactory(), KingdomsXExtensionFactory::createExtension);
|
||||
register(new JobsExtensionFactory(), JobsExtensionFactory::createExtension);
|
||||
@ -88,7 +88,7 @@ public class ExtensionRegister {
|
||||
register(new McMMOExtensionFactory(), McMMOExtensionFactory::createExtension, McMMOExtensionFactory::registerExpansion);
|
||||
registerMany(new MinigameLibExtensionFactory(), MinigameLibExtensionFactory::createExtensions);
|
||||
register(new MyPetExtensionFactory(), MyPetExtensionFactory::createExtension);
|
||||
register(new NucleusExtensionFactory(), NucleusExtensionFactory::createExtension);
|
||||
//register(new NucleusExtensionFactory(), NucleusExtensionFactory::createExtension); // TODO: update for Sponge API 8
|
||||
register(new NuVotifierExtensionFactory(), NuVotifierExtensionFactory::createExtension);
|
||||
register(new PlaceholderAPIExtensionFactory(), PlaceholderAPIExtensionFactory::createExtension);
|
||||
register(new PlotSquaredExtensionFactory(), PlotSquaredExtensionFactory::createExtension);
|
||||
|
@ -13,9 +13,17 @@ dependencies {
|
||||
testImplementation project(path: ":velocity", configuration: 'testArtifacts')
|
||||
}
|
||||
|
||||
jar {
|
||||
// Add the sponge mixin into the manifest
|
||||
manifest.attributes([
|
||||
'MixinConfigs': 'plan-sponge.mixins.json'
|
||||
])
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate('org.apache', 'plan.org.apache') {
|
||||
exclude 'org/apache/logging/**'
|
||||
exclude 'org/apache/maven/**' // This needs to be unrelocated for Sponge
|
||||
}
|
||||
relocate 'dagger', 'plan.dagger'
|
||||
// Don't relocate MySQL or SQLite since they are loaded with a isolated class loader
|
||||
|
@ -1,10 +1,9 @@
|
||||
plugins {
|
||||
id "net.kyori.blossom" version "1.3.0"
|
||||
}
|
||||
import org.spongepowered.gradle.plugin.config.PluginLoaders
|
||||
import org.spongepowered.gradle.vanilla.repository.MinecraftPlatform
|
||||
|
||||
blossom {
|
||||
replaceTokenIn('src/main/java/com/djrapitops/plan/PlanSponge.java')
|
||||
replaceToken('@version@', '' + project.ext.fullVersion)
|
||||
plugins {
|
||||
id "org.spongepowered.gradle.plugin" version "2.0.0"
|
||||
id "org.spongepowered.gradle.vanilla" version "0.2"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@ -15,14 +14,63 @@ dependencies {
|
||||
implementation "net.playeranalytics:platform-abstraction-layer-sponge:$palVersion"
|
||||
implementation "org.bstats:bstats-sponge:$bstatsVersion"
|
||||
|
||||
compileOnly "org.spongepowered:spongeapi:$spongeVersion"
|
||||
testImplementation "org.spongepowered:spongeapi:$spongeVersion"
|
||||
|
||||
annotationProcessor "org.spongepowered:spongeapi:$spongeVersion"
|
||||
implementation "org.spongepowered:mixin:0.7.11-SNAPSHOT"
|
||||
|
||||
testImplementation project(path: ":common", configuration: 'testArtifacts')
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate 'org.bstats', 'com.djrapitops.plan.utilities.metrics'
|
||||
sponge {
|
||||
apiVersion(spongeVersion)
|
||||
license("LGPLv3")
|
||||
loader {
|
||||
name(PluginLoaders.JAVA_PLAIN)
|
||||
version("1.0")
|
||||
}
|
||||
plugin("plan") {
|
||||
displayName("Plan")
|
||||
version(fullVersion)
|
||||
entrypoint("com.djrapitops.plan.PlanSponge")
|
||||
description("Player Analytics Plugin by AuroraLS3")
|
||||
contributor("AuroraLS3") {
|
||||
description("Author")
|
||||
}
|
||||
|
||||
// Dependencies
|
||||
// version is a *required* property (empty string works fine)
|
||||
dependency("griefprevention") {
|
||||
optional(true)
|
||||
version("")
|
||||
}
|
||||
dependency("luckperms") {
|
||||
optional(true)
|
||||
version("")
|
||||
}
|
||||
dependency("nucleus") {
|
||||
optional(true)
|
||||
version("")
|
||||
}
|
||||
dependency("redprotect") {
|
||||
optional(true)
|
||||
version("")
|
||||
}
|
||||
dependency("nuvotifier") {
|
||||
optional(true)
|
||||
version("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
minecraft {
|
||||
version("1.16.5")
|
||||
platform(MinecraftPlatform.JOINED)
|
||||
}
|
||||
|
||||
compileJava {
|
||||
options.release = 11
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
relocate "org.bstats", "com.djrapitops.plan.utilities.metrics"
|
||||
}
|
@ -29,24 +29,24 @@ import net.playeranalytics.plugin.SpongePlatformLayer;
|
||||
import net.playeranalytics.plugin.scheduling.RunnableFactory;
|
||||
import net.playeranalytics.plugin.server.PluginLogger;
|
||||
import org.bstats.sponge.Metrics;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.api.Game;
|
||||
import org.spongepowered.api.Server;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.command.CommandManager;
|
||||
import org.spongepowered.api.command.CommandMapping;
|
||||
import org.spongepowered.api.command.Command;
|
||||
import org.spongepowered.api.config.ConfigDir;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.game.state.GamePreInitializationEvent;
|
||||
import org.spongepowered.api.event.game.state.GameStartedServerEvent;
|
||||
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
|
||||
import org.spongepowered.api.plugin.Dependency;
|
||||
import org.spongepowered.api.plugin.Plugin;
|
||||
import org.spongepowered.api.scheduler.Task;
|
||||
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.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
@ -54,26 +54,14 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
|
||||
@Plugin(
|
||||
id = "plan",
|
||||
name = "Plan",
|
||||
version = "@version@",
|
||||
description = "Player Analytics Plugin by AuroraLS3",
|
||||
authors = {"AuroraLS3"},
|
||||
dependencies = {
|
||||
@Dependency(id = "griefprevention", optional = true),
|
||||
@Dependency(id = "luckperms", optional = true),
|
||||
@Dependency(id = "nucleus", optional = true),
|
||||
@Dependency(id = "redprotect", optional = true),
|
||||
@Dependency(id = "nuvotifier", optional = true)
|
||||
}
|
||||
)
|
||||
@Plugin("plan")
|
||||
public class PlanSponge implements PlanPlugin {
|
||||
|
||||
private final Metrics metrics;
|
||||
private final Logger slf4jLogger;
|
||||
private final PluginContainer plugin;
|
||||
private final File dataFolder;
|
||||
|
||||
private PlanSpongeComponent component;
|
||||
private PlanSystem system;
|
||||
private Locale locale;
|
||||
private ServerShutdownSave serverShutdownSave;
|
||||
@ -83,57 +71,93 @@ public class PlanSponge implements PlanPlugin {
|
||||
|
||||
@com.google.inject.Inject
|
||||
public PlanSponge(
|
||||
Logger slf4jLogger,
|
||||
@ConfigDir(sharedRoot = false) File dataFolder,
|
||||
@ConfigDir(sharedRoot = false) Path dataFolder,
|
||||
PluginContainer plugin,
|
||||
Metrics.Factory metrics
|
||||
) {
|
||||
this.slf4jLogger = slf4jLogger;
|
||||
this.dataFolder = dataFolder;
|
||||
this.dataFolder = dataFolder.toFile();
|
||||
this.plugin = plugin;
|
||||
|
||||
int pluginId = 3086;
|
||||
this.metrics = metrics.make(pluginId);
|
||||
}
|
||||
|
||||
private final Map<String, CommandMapping> commands = new HashMap<>();
|
||||
|
||||
@Listener
|
||||
public void onServerLoad(GamePreInitializationEvent event) {
|
||||
public void onServerLoad(ConstructPluginEvent event) {
|
||||
onLoad();
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onServerStart(GameStartedServerEvent event) {
|
||||
public void onServerStart(StartingEngineEvent<Server> event) {
|
||||
onEnable();
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onServerStop(GameStoppingServerEvent event) {
|
||||
public void onServerStop(StoppingEngineEvent<Server> event) {
|
||||
onDisable();
|
||||
}
|
||||
|
||||
private void onLoad() {
|
||||
abstractionLayer = new SpongePlatformLayer(this, dataFolder, slf4jLogger);
|
||||
abstractionLayer = new SpongePlatformLayer(plugin, dataFolder);
|
||||
logger = abstractionLayer.getPluginLogger();
|
||||
runnableFactory = abstractionLayer.getRunnableFactory();
|
||||
|
||||
catchStartupErrors(() -> {
|
||||
component = makeComponent();
|
||||
system = component.system();
|
||||
system.enableForCommands();
|
||||
});
|
||||
}
|
||||
|
||||
public void onEnable() {
|
||||
PlanSpongeComponent component = DaggerPlanSpongeComponent.builder()
|
||||
.plan(this)
|
||||
.abstractionLayer(abstractionLayer)
|
||||
.game(Sponge.getGame())
|
||||
.build();
|
||||
try {
|
||||
catchStartupErrors(() -> {
|
||||
boolean firstBoot = component != null;
|
||||
if (firstBoot && system == null) {
|
||||
// Already failed to load. Prevent throwing any more errors than necessary
|
||||
return;
|
||||
}
|
||||
|
||||
if (!firstBoot) {
|
||||
// Reinitialize component & system
|
||||
component = makeComponent();
|
||||
system = component.system();
|
||||
}
|
||||
|
||||
serverShutdownSave = component.serverShutdownSave();
|
||||
locale = system.getLocaleSystem().getLocale();
|
||||
|
||||
if (firstBoot) {
|
||||
// First boot, only enable what isn't already enabled
|
||||
system.enableOtherThanCommands();
|
||||
} else {
|
||||
// Not first boot, enable everything normally
|
||||
system.enable();
|
||||
}
|
||||
|
||||
new BStatsSponge(
|
||||
metrics, system.getDatabaseSystem().getDatabase()
|
||||
).registerMetrics();
|
||||
|
||||
logger.info(locale.getString(PluginLang.ENABLED));
|
||||
});
|
||||
|
||||
// Registering command is done through onRegisterCommand
|
||||
if (system != null) {
|
||||
system.getProcessing().submitNonCritical(() -> system.getListenerSystem().callEnableEvent(this));
|
||||
}
|
||||
}
|
||||
|
||||
private PlanSpongeComponent makeComponent() {
|
||||
return DaggerPlanSpongeComponent.builder()
|
||||
.plan(this)
|
||||
.abstractionLayer(abstractionLayer)
|
||||
.game(Sponge.game())
|
||||
.build();
|
||||
}
|
||||
|
||||
private void catchStartupErrors(Runnable task) {
|
||||
try {
|
||||
task.run();
|
||||
} catch (AbstractMethodError e) {
|
||||
logger.error("Plugin ran into AbstractMethodError - Server restart is required. Likely cause is updating the jar without a restart.");
|
||||
} catch (EnableException e) {
|
||||
@ -149,13 +173,10 @@ public class PlanSponge implements PlanPlugin {
|
||||
logger.error("This error should be reported at https://github.com/plan-player-analytics/Plan/issues");
|
||||
onDisable();
|
||||
}
|
||||
registerCommand(component.planCommand().build());
|
||||
if (system != null) {
|
||||
system.getProcessing().submitNonCritical(() -> system.getListenerSystem().callEnableEvent(this));
|
||||
}
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
component = null;
|
||||
storeSessionsOnShutdown();
|
||||
cancelAllTasks();
|
||||
if (system != null) system.disable();
|
||||
@ -182,9 +203,6 @@ public class PlanSponge implements PlanPlugin {
|
||||
|
||||
public void cancelAllTasks() {
|
||||
runnableFactory.cancelAllKnownTasks();
|
||||
for (Task task : Sponge.getScheduler().getScheduledTasks(this)) {
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -199,21 +217,23 @@ public class PlanSponge implements PlanPlugin {
|
||||
|
||||
@Override
|
||||
public void registerCommand(Subcommand command) {
|
||||
if (command == null) {
|
||||
logger.warn("Attempted to register a null command!");
|
||||
return;
|
||||
}
|
||||
for (String name : command.getAliases()) {
|
||||
CommandManager commandManager = Sponge.getCommandManager();
|
||||
|
||||
CommandMapping registered = commands.get(name);
|
||||
if (registered != null) {
|
||||
commandManager.removeMapping(registered);
|
||||
// NOOP: Sponge commands are registered via the event below
|
||||
}
|
||||
|
||||
Optional<CommandMapping> register = commandManager.register(this, new SpongeCommand(runnableFactory, system.getErrorLogger(), command), name);
|
||||
register.ifPresent(commandMapping -> commands.put(name, commandMapping));
|
||||
}
|
||||
@Listener
|
||||
public void onRegisterCommand(RegisterCommandEvent<Command.Raw> event) {
|
||||
Subcommand command = component.planCommand().build();
|
||||
List<String> aliases = new ArrayList<>(command.getAliases());
|
||||
event.register(
|
||||
plugin,
|
||||
new SpongeCommand(
|
||||
runnableFactory,
|
||||
() -> component,
|
||||
command
|
||||
),
|
||||
aliases.remove(0),
|
||||
aliases.toArray(new String[0])
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -222,7 +242,11 @@ public class PlanSponge implements PlanPlugin {
|
||||
}
|
||||
|
||||
public Game getGame() {
|
||||
return Sponge.getGame();
|
||||
return Sponge.game();
|
||||
}
|
||||
|
||||
public PluginContainer getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -21,10 +21,10 @@ import com.djrapitops.plan.settings.locale.Locale;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorLogger;
|
||||
import net.playeranalytics.plugin.server.PluginLogger;
|
||||
import org.spongepowered.api.GameState;
|
||||
import org.spongepowered.api.Server;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.Order;
|
||||
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
|
||||
import org.spongepowered.api.event.lifecycle.StoppingEngineEvent;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -55,11 +55,7 @@ public class SpongeServerShutdownSave extends ServerShutdownSave {
|
||||
}
|
||||
|
||||
@Listener(order = Order.PRE)
|
||||
public void onServerShutdown(GameStoppingServerEvent event) {
|
||||
GameState state = event.getState();
|
||||
shuttingDown = state == GameState.SERVER_STOPPING
|
||||
|| state == GameState.GAME_STOPPING
|
||||
|| state == GameState.SERVER_STOPPED
|
||||
|| state == GameState.GAME_STOPPED;
|
||||
public void onServerShutdown(StoppingEngineEvent<Server> event) {
|
||||
shuttingDown = true;
|
||||
}
|
||||
}
|
@ -17,8 +17,8 @@
|
||||
package com.djrapitops.plan.api.events;
|
||||
|
||||
import com.djrapitops.plan.PlanSponge;
|
||||
import org.spongepowered.api.event.cause.Cause;
|
||||
import org.spongepowered.api.event.cause.EventContext;
|
||||
import org.spongepowered.api.event.Cause;
|
||||
import org.spongepowered.api.event.EventContext;
|
||||
import org.spongepowered.api.event.impl.AbstractEvent;
|
||||
|
||||
/**
|
||||
@ -50,17 +50,17 @@ public class PlanSpongeEnableEvent extends AbstractEvent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cause getCause() {
|
||||
public Cause cause() {
|
||||
return Cause.builder().append(plugin.getSystem()).build(EventContext.empty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSource() {
|
||||
public Object source() {
|
||||
return plugin.getSystem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventContext getContext() {
|
||||
public EventContext context() {
|
||||
return EventContext.empty();
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,10 @@
|
||||
*/
|
||||
package com.djrapitops.plan.commands.use;
|
||||
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.text.Text;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.identity.Identity;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
@ -25,15 +27,21 @@ import java.util.UUID;
|
||||
|
||||
public class SpongeCMDSender implements CMDSender {
|
||||
|
||||
final CommandSource source;
|
||||
final Subject subject;
|
||||
final Audience audience;
|
||||
|
||||
public SpongeCMDSender(CommandSource source) {
|
||||
this.source = source;
|
||||
public <T extends Subject & Audience> SpongeCMDSender(T source) {
|
||||
this(source, source);
|
||||
}
|
||||
|
||||
public SpongeCMDSender(Subject subject, Audience audience) {
|
||||
this.subject = subject;
|
||||
this.audience = audience;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder buildMessage() {
|
||||
return new SpongeMessageBuilder(this);
|
||||
return new AdventureMessageBuilder(this, audience);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -43,7 +51,7 @@ public class SpongeCMDSender implements CMDSender {
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return source.hasPermission(permission);
|
||||
return subject.hasPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -53,7 +61,7 @@ public class SpongeCMDSender implements CMDSender {
|
||||
|
||||
@Override
|
||||
public void send(String text) {
|
||||
source.sendMessage(Text.of(text));
|
||||
audience.sendMessage(Identity.nil(), LegacyComponentSerializer.legacySection().deserialize(text));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -66,11 +74,11 @@ public class SpongeCMDSender implements CMDSender {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
SpongeCMDSender that = (SpongeCMDSender) o;
|
||||
return source.equals(that.source);
|
||||
return subject.identifier().equals(that.subject.identifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(source);
|
||||
return Objects.hash(subject.identifier());
|
||||
}
|
||||
}
|
||||
|
@ -16,46 +16,85 @@
|
||||
*/
|
||||
package com.djrapitops.plan.commands.use;
|
||||
|
||||
import com.djrapitops.plan.PlanSpongeComponent;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorContext;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorLogger;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import net.playeranalytics.plugin.scheduling.RunnableFactory;
|
||||
import org.spongepowered.api.command.CommandCallable;
|
||||
import org.spongepowered.api.command.Command;
|
||||
import org.spongepowered.api.command.CommandCause;
|
||||
import org.spongepowered.api.command.CommandCompletion;
|
||||
import org.spongepowered.api.command.CommandResult;
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.command.source.RconSource;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.text.Text;
|
||||
import org.spongepowered.api.world.Location;
|
||||
import org.spongepowered.api.world.World;
|
||||
import org.spongepowered.api.command.parameter.ArgumentReader;
|
||||
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
|
||||
import org.spongepowered.api.network.RconConnection;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SpongeCommand implements CommandCallable {
|
||||
public class SpongeCommand implements Command.Raw {
|
||||
|
||||
private final RunnableFactory runnableFactory;
|
||||
private final ErrorLogger errorLogger;
|
||||
private final Subcommand command;
|
||||
private final Supplier<PlanSpongeComponent> componentSupplier;
|
||||
private PlanSpongeComponent commandComponent;
|
||||
private ErrorLogger errorLogger;
|
||||
private Subcommand subcommand;
|
||||
|
||||
public SpongeCommand(
|
||||
RunnableFactory runnableFactory,
|
||||
ErrorLogger errorLogger, Subcommand command
|
||||
Supplier<PlanSpongeComponent> componentSupplier,
|
||||
Subcommand initialCommand
|
||||
) {
|
||||
this.runnableFactory = runnableFactory;
|
||||
this.errorLogger = errorLogger;
|
||||
this.command = command;
|
||||
this.componentSupplier = componentSupplier;
|
||||
this.commandComponent = componentSupplier.get();
|
||||
this.errorLogger = commandComponent.system().getErrorLogger();
|
||||
this.subcommand = initialCommand;
|
||||
}
|
||||
|
||||
private synchronized Subcommand getCommand() {
|
||||
PlanSpongeComponent component = componentSupplier.get();
|
||||
// Check if the component has changed, if it has, update the command and error logger.
|
||||
if (commandComponent != component) {
|
||||
errorLogger = component.system().getErrorLogger();
|
||||
subcommand = component.planCommand().build();
|
||||
commandComponent = component;
|
||||
}
|
||||
|
||||
return subcommand;
|
||||
}
|
||||
|
||||
private CMDSender getSender(CommandCause cause) {
|
||||
return getSender(cause.subject(), cause.audience());
|
||||
}
|
||||
|
||||
private CMDSender getSender(Subject subject, Audience audience) {
|
||||
if (subject instanceof ServerPlayer || subject instanceof RconConnection) {
|
||||
return new SpongePlayerCMDSender(subject, audience);
|
||||
} else {
|
||||
return new SpongeCMDSender(subject, audience);
|
||||
}
|
||||
}
|
||||
|
||||
private Component convertLegacy(String legacy) {
|
||||
return LegacyComponentSerializer.legacySection().deserialize(legacy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult process(CommandSource source, String arguments) {
|
||||
public CommandResult process(CommandCause cause, ArgumentReader.Mutable arguments) {
|
||||
runnableFactory.create(() -> {
|
||||
try {
|
||||
command.getExecutor().accept(getSender(source), new Arguments(arguments));
|
||||
getCommand().getExecutor().accept(getSender(cause), new Arguments(arguments.input()));
|
||||
} catch (Exception e) {
|
||||
errorLogger.error(e, ErrorContext.builder()
|
||||
.related(source.getClass())
|
||||
.related(cause.subject().getClass())
|
||||
.related(arguments)
|
||||
.build());
|
||||
}
|
||||
@ -63,22 +102,17 @@ public class SpongeCommand implements CommandCallable {
|
||||
return CommandResult.success();
|
||||
}
|
||||
|
||||
private CMDSender getSender(CommandSource source) {
|
||||
if (source instanceof Player || source instanceof RconSource) {
|
||||
return new SpongePlayerCMDSender(source);
|
||||
} else {
|
||||
return new SpongeCMDSender(source);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSuggestions(CommandSource source, String arguments, @Nullable Location<World> targetPosition) {
|
||||
public List<CommandCompletion> complete(CommandCause cause, ArgumentReader.Mutable arguments) {
|
||||
try {
|
||||
return command.getArgumentResolver()
|
||||
.apply(getSender(source), new Arguments(arguments));
|
||||
return getCommand().getArgumentResolver()
|
||||
.apply(getSender(cause), new Arguments(arguments.input()))
|
||||
.stream()
|
||||
.map(CommandCompletion::of)
|
||||
.collect(Collectors.toList());
|
||||
} catch (Exception e) {
|
||||
errorLogger.error(e, ErrorContext.builder()
|
||||
.related(source.getClass())
|
||||
.related(cause.subject().getClass())
|
||||
.related("tab completion")
|
||||
.related(arguments)
|
||||
.build());
|
||||
@ -87,9 +121,9 @@ public class SpongeCommand implements CommandCallable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean testPermission(CommandSource source) {
|
||||
for (String requiredPermission : command.getRequiredPermissions()) {
|
||||
if (!source.hasPermission(requiredPermission)) {
|
||||
public boolean canExecute(CommandCause cause) {
|
||||
for (String requiredPermission : getCommand().getRequiredPermissions()) {
|
||||
if (!cause.subject().hasPermission(requiredPermission)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -97,17 +131,26 @@ public class SpongeCommand implements CommandCallable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Text> getShortDescription(CommandSource source) {
|
||||
return Optional.ofNullable(command.getDescription()).map(Text::of);
|
||||
public Optional<Component> shortDescription(CommandCause cause) {
|
||||
return Optional.ofNullable(getCommand().getDescription()).map(this::convertLegacy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Text> getHelp(CommandSource source) {
|
||||
return Optional.ofNullable(command.getDescription()).map(Text::of);
|
||||
public Optional<Component> extendedDescription(CommandCause cause) {
|
||||
return Optional.ofNullable(getCommand().getDescription()).map(this::convertLegacy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Text getUsage(CommandSource source) {
|
||||
return Text.of(command.getInDepthDescription());
|
||||
public Component usage(CommandCause cause) {
|
||||
TextComponent.Builder builder = Component.text();
|
||||
List<String> lines = getCommand().getInDepthDescription();
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
String line = lines.get(i);
|
||||
builder.append(convertLegacy(line));
|
||||
if (i < lines.size() - 1) {
|
||||
builder.append(Component.newline());
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
@ -1,113 +0,0 @@
|
||||
/*
|
||||
* This file is part of Player Analytics (Plan).
|
||||
*
|
||||
* Plan is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License v3 as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Plan 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.djrapitops.plan.commands.use;
|
||||
|
||||
import org.apache.commons.text.TextStringBuilder;
|
||||
import org.spongepowered.api.text.Text;
|
||||
import org.spongepowered.api.text.action.TextActions;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
|
||||
public class SpongeMessageBuilder implements MessageBuilder {
|
||||
|
||||
private final SpongeCMDSender sender;
|
||||
private final Text.Builder builder;
|
||||
private final SpongeMessageBuilder previous;
|
||||
|
||||
public SpongeMessageBuilder(SpongeCMDSender sender) {
|
||||
this(sender, null);
|
||||
}
|
||||
|
||||
SpongeMessageBuilder(SpongeCMDSender sender, SpongeMessageBuilder previous) {
|
||||
this.sender = sender;
|
||||
this.builder = Text.builder();
|
||||
this.previous = previous;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder addPart(String s) {
|
||||
SpongeMessageBuilder newBuilder = new SpongeMessageBuilder(sender, this);
|
||||
newBuilder.builder.append(Text.of(s));
|
||||
return newBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder newLine() {
|
||||
builder.append(Text.of('\n'));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder link(String url) {
|
||||
try {
|
||||
builder.onClick(TextActions.openUrl(new URL(url)));
|
||||
} catch (MalformedURLException e) {
|
||||
throw new IllegalArgumentException("'" + url + "' is not a valid URL");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder command(String command) {
|
||||
builder.onClick(TextActions.runCommand(command.charAt(0) == '/' ? command : '/' + command));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder hover(String message) {
|
||||
builder.onHover(TextActions.showText(Text.of(message)));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder hover(String... lines) {
|
||||
builder.onHover(TextActions.showText(Text.of(new TextStringBuilder().appendWithSeparators(lines, "\n"))));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder hover(Collection<String> lines) {
|
||||
builder.onHover(TextActions.showText(Text.of(new TextStringBuilder().appendWithSeparators(lines, "\n"))));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder indent(int amount) {
|
||||
for (int i = 0; i < amount; i++) {
|
||||
builder.append(Text.of(' '));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageBuilder tabular(CharSequence charSequence) {
|
||||
addPart(sender.getFormatter().table(charSequence.toString(), ":"));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send() {
|
||||
if (previous == null) {
|
||||
sender.source.sendMessage(builder.build());
|
||||
} else {
|
||||
previous.builder.append(builder.build());
|
||||
previous.send();
|
||||
}
|
||||
}
|
||||
}
|
@ -16,27 +16,32 @@
|
||||
*/
|
||||
package com.djrapitops.plan.commands.use;
|
||||
|
||||
import org.spongepowered.api.command.CommandSource;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
|
||||
import org.spongepowered.api.service.permission.Subject;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SpongePlayerCMDSender extends SpongeCMDSender {
|
||||
|
||||
public SpongePlayerCMDSender(CommandSource source) {
|
||||
super(source);
|
||||
public <T extends Subject & Audience> SpongePlayerCMDSender(T source) {
|
||||
this(source, source);
|
||||
}
|
||||
|
||||
public SpongePlayerCMDSender(Subject subject, Audience audience) {
|
||||
super(subject, audience);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getPlayerName() {
|
||||
return source.getFriendlyIdentifier();
|
||||
return subject.friendlyIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<UUID> getUUID() {
|
||||
if (source instanceof Player) {
|
||||
return Optional.of(((Player) source).getUniqueId());
|
||||
if (subject instanceof ServerPlayer) {
|
||||
return Optional.of(((ServerPlayer) subject).uniqueId());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
@ -17,15 +17,15 @@
|
||||
package com.djrapitops.plan.gathering;
|
||||
|
||||
import org.spongepowered.api.Game;
|
||||
import org.spongepowered.api.world.Chunk;
|
||||
import org.spongepowered.api.world.World;
|
||||
import org.spongepowered.api.world.chunk.WorldChunk;
|
||||
import org.spongepowered.api.world.server.ServerWorld;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Iterator;
|
||||
|
||||
@Singleton
|
||||
public class SpongeSensor implements ServerSensor<World> {
|
||||
public class SpongeSensor implements ServerSensor<ServerWorld> {
|
||||
|
||||
private final Game game;
|
||||
|
||||
@ -41,26 +41,26 @@ public class SpongeSensor implements ServerSensor<World> {
|
||||
|
||||
@Override
|
||||
public int getOnlinePlayerCount() {
|
||||
return game.getServer().getOnlinePlayers().size();
|
||||
return game.server().onlinePlayers().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getTPS() {
|
||||
return game.getServer().getTicksPerSecond();
|
||||
return game.server().ticksPerSecond();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<World> getWorlds() {
|
||||
return game.getServer().getWorlds();
|
||||
public Iterable<ServerWorld> getWorlds() {
|
||||
return game.server().worldManager().worlds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChunkCount(World world) {
|
||||
public int getChunkCount(ServerWorld world) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int getLaggyChunkCount(World world) {
|
||||
Iterator<Chunk> chunks = world.getLoadedChunks().iterator();
|
||||
private int getLaggyChunkCount(ServerWorld world) {
|
||||
Iterator<WorldChunk> chunks = world.loadedChunks().iterator();
|
||||
int count = 0;
|
||||
while (chunks.hasNext()) {
|
||||
chunks.next();
|
||||
@ -70,7 +70,7 @@ public class SpongeSensor implements ServerSensor<World> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntityCount(World world) {
|
||||
return world.getEntities().size();
|
||||
public int getEntityCount(ServerWorld world) {
|
||||
return world.entities().size();
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ import com.djrapitops.plan.SpongeServerShutdownSave;
|
||||
import com.djrapitops.plan.api.events.PlanSpongeEnableEvent;
|
||||
import com.djrapitops.plan.capability.CapabilitySvc;
|
||||
import com.djrapitops.plan.gathering.listeners.sponge.*;
|
||||
import com.djrapitops.plan.gathering.listeners.sponge.SpongeGMChangeListener;
|
||||
import net.playeranalytics.plugin.server.Listeners;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.event.Event;
|
||||
@ -82,7 +83,7 @@ public class SpongeListenerSystem extends ListenerSystem {
|
||||
public void callEnableEvent(PlanPlugin plugin) {
|
||||
try {
|
||||
Event event = new PlanSpongeEnableEvent((PlanSponge) plugin);
|
||||
Sponge.getEventManager().post(event);
|
||||
Sponge.eventManager().post(event);
|
||||
} catch (IllegalStateException ignore) {
|
||||
/* Ignore, Sponge is not initialized */
|
||||
}
|
||||
|
@ -39,16 +39,18 @@ import com.djrapitops.plan.storage.database.Database;
|
||||
import com.djrapitops.plan.storage.database.transactions.events.*;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorContext;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorLogger;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.data.key.Keys;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.entity.living.player.gamemode.GameMode;
|
||||
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.Order;
|
||||
import org.spongepowered.api.event.entity.living.humanoid.player.KickPlayerEvent;
|
||||
import org.spongepowered.api.event.network.ClientConnectionEvent;
|
||||
import org.spongepowered.api.event.entity.living.player.KickPlayerEvent;
|
||||
import org.spongepowered.api.event.network.ServerSideConnectionEvent;
|
||||
import org.spongepowered.api.profile.GameProfile;
|
||||
import org.spongepowered.api.service.ProviderRegistration;
|
||||
import org.spongepowered.api.registry.RegistryTypes;
|
||||
import org.spongepowered.api.service.ban.Ban;
|
||||
import org.spongepowered.api.service.ban.BanService;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@ -103,7 +105,7 @@ public class PlayerOnlineListener {
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onLogin(ClientConnectionEvent.Login event) {
|
||||
public void onLogin(ServerSideConnectionEvent.Login event) {
|
||||
try {
|
||||
actOnLoginEvent(event);
|
||||
} catch (Exception e) {
|
||||
@ -111,9 +113,9 @@ public class PlayerOnlineListener {
|
||||
}
|
||||
}
|
||||
|
||||
private void actOnLoginEvent(ClientConnectionEvent.Login event) {
|
||||
GameProfile profile = event.getProfile();
|
||||
UUID playerUUID = profile.getUniqueId();
|
||||
private void actOnLoginEvent(ServerSideConnectionEvent.Login event) {
|
||||
GameProfile profile = event.profile();
|
||||
UUID playerUUID = profile.uniqueId();
|
||||
ServerUUID serverUUID = serverInfo.getServerUUID();
|
||||
dbSystem.getDatabase().executeTransaction(new BanStatusTransaction(playerUUID, serverUUID, () -> isBanned(profile)));
|
||||
}
|
||||
@ -121,7 +123,7 @@ public class PlayerOnlineListener {
|
||||
@Listener(order = Order.POST)
|
||||
public void onKick(KickPlayerEvent event) {
|
||||
try {
|
||||
UUID playerUUID = event.getTargetEntity().getUniqueId();
|
||||
UUID playerUUID = event.player().uniqueId();
|
||||
if (status.areKicksNotCounted() || SpongeAFKListener.afkTracker.isAfk(playerUUID)) {
|
||||
return;
|
||||
}
|
||||
@ -132,16 +134,13 @@ public class PlayerOnlineListener {
|
||||
}
|
||||
|
||||
private boolean isBanned(GameProfile profile) {
|
||||
Optional<ProviderRegistration<BanService>> banService = Sponge.getServiceManager().getRegistration(BanService.class);
|
||||
boolean banned = false;
|
||||
if (banService.isPresent()) {
|
||||
banned = banService.get().getProvider().isBanned(profile);
|
||||
}
|
||||
return banned;
|
||||
BanService banService = Sponge.server().serviceProvider().banService();
|
||||
Optional<Ban.Profile> ban = banService.find(profile).join();
|
||||
return ban.isPresent();
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onJoin(ClientConnectionEvent.Join event) {
|
||||
public void onJoin(ServerSideConnectionEvent.Join event) {
|
||||
try {
|
||||
actOnJoinEvent(event);
|
||||
} catch (Exception e) {
|
||||
@ -149,27 +148,28 @@ public class PlayerOnlineListener {
|
||||
}
|
||||
}
|
||||
|
||||
private void actOnJoinEvent(ClientConnectionEvent.Join event) {
|
||||
Player player = event.getTargetEntity();
|
||||
private void actOnJoinEvent(ServerSideConnectionEvent.Join event) {
|
||||
ServerPlayer player = event.player();
|
||||
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
UUID playerUUID = player.uniqueId();
|
||||
ServerUUID serverUUID = serverInfo.getServerUUID();
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
SpongeAFKListener.afkTracker.performedAction(playerUUID, time);
|
||||
|
||||
String world = player.getWorld().getName();
|
||||
Optional<GameMode> gameMode = player.getGameModeData().get(Keys.GAME_MODE);
|
||||
String gm = gameMode.map(mode -> mode.getName().toUpperCase()).orElse("ADVENTURE");
|
||||
String world = Sponge.game().server().worldManager().worldDirectory(player.world().key())
|
||||
.map(path -> path.getFileName().toString()).orElse("Unknown");
|
||||
GameMode gameMode = player.gameMode().get();
|
||||
String gm = gameMode.key(RegistryTypes.GAME_MODE).value().toUpperCase();
|
||||
|
||||
Database database = dbSystem.getDatabase();
|
||||
database.executeTransaction(new WorldNameStoreTransaction(serverUUID, world));
|
||||
|
||||
InetAddress address = player.getConnection().getAddress().getAddress();
|
||||
Supplier<String> getHostName = () -> player.getConnection().getVirtualHost().getHostString();
|
||||
InetAddress address = player.connection().address().getAddress();
|
||||
Supplier<String> getHostName = () -> player.connection().virtualHost().getHostString();
|
||||
|
||||
String playerName = player.getName();
|
||||
String displayName = player.getDisplayNameData().displayName().get().toPlain();
|
||||
String playerName = player.name();
|
||||
String displayName = LegacyComponentSerializer.legacyAmpersand().serialize(player.displayName().get());
|
||||
|
||||
database.executeTransaction(new PlayerServerRegisterTransaction(playerUUID, () -> time,
|
||||
playerName, serverUUID, getHostName))
|
||||
@ -203,15 +203,15 @@ public class PlayerOnlineListener {
|
||||
}
|
||||
|
||||
@Listener(order = Order.DEFAULT)
|
||||
public void beforeQuit(ClientConnectionEvent.Disconnect event) {
|
||||
Player player = event.getTargetEntity();
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
String playerName = player.getName();
|
||||
public void beforeQuit(ServerSideConnectionEvent.Disconnect event) {
|
||||
Player player = event.player();
|
||||
UUID playerUUID = player.uniqueId();
|
||||
String playerName = player.name();
|
||||
processing.submitNonCritical(() -> extensionService.updatePlayerValues(playerUUID, playerName, CallEvents.PLAYER_LEAVE));
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onQuit(ClientConnectionEvent.Disconnect event) {
|
||||
public void onQuit(ServerSideConnectionEvent.Disconnect event) {
|
||||
try {
|
||||
actOnQuitEvent(event);
|
||||
} catch (Exception e) {
|
||||
@ -219,18 +219,18 @@ public class PlayerOnlineListener {
|
||||
}
|
||||
}
|
||||
|
||||
private void actOnQuitEvent(ClientConnectionEvent.Disconnect event) {
|
||||
private void actOnQuitEvent(ServerSideConnectionEvent.Disconnect event) {
|
||||
long time = System.currentTimeMillis();
|
||||
Player player = event.getTargetEntity();
|
||||
String playerName = player.getName();
|
||||
UUID playerUUID = player.getUniqueId();
|
||||
Player player = event.player();
|
||||
String playerName = player.name();
|
||||
UUID playerUUID = player.uniqueId();
|
||||
ServerUUID serverUUID = serverInfo.getServerUUID();
|
||||
|
||||
SpongeAFKListener.afkTracker.loggedOut(playerUUID, time);
|
||||
|
||||
nicknameCache.removeDisplayName(playerUUID);
|
||||
|
||||
dbSystem.getDatabase().executeTransaction(new BanStatusTransaction(playerUUID, serverUUID, () -> isBanned(player.getProfile())));
|
||||
dbSystem.getDatabase().executeTransaction(new BanStatusTransaction(playerUUID, serverUUID, () -> isBanned(player.profile())));
|
||||
|
||||
sessionCache.endSession(playerUUID, time)
|
||||
.ifPresent(endedSession -> dbSystem.getDatabase().executeTransaction(new StoreSessionTransaction(endedSession)));
|
||||
|
@ -21,16 +21,16 @@ import com.djrapitops.plan.settings.Permissions;
|
||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorContext;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorLogger;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
|
||||
import org.spongepowered.api.event.Event;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.Order;
|
||||
import org.spongepowered.api.event.command.SendCommandEvent;
|
||||
import org.spongepowered.api.event.command.ExecuteCommandEvent;
|
||||
import org.spongepowered.api.event.entity.MoveEntityEvent;
|
||||
import org.spongepowered.api.event.entity.living.humanoid.player.PlayerChangeClientSettingsEvent;
|
||||
import org.spongepowered.api.event.entity.living.humanoid.player.TargetPlayerEvent;
|
||||
import org.spongepowered.api.event.entity.living.player.PlayerChangeClientSettingsEvent;
|
||||
import org.spongepowered.api.event.filter.cause.First;
|
||||
import org.spongepowered.api.event.message.MessageChannelEvent;
|
||||
import org.spongepowered.api.event.network.ClientConnectionEvent;
|
||||
import org.spongepowered.api.event.message.PlayerChatEvent;
|
||||
import org.spongepowered.api.event.network.ServerSideConnectionEvent;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Map;
|
||||
@ -67,26 +67,26 @@ public class SpongeAFKListener {
|
||||
}
|
||||
}
|
||||
|
||||
private void event(TargetPlayerEvent event) {
|
||||
private void event(Event event, ServerPlayer player) {
|
||||
try {
|
||||
performedAction(event.getTargetEntity());
|
||||
performedAction(player);
|
||||
} catch (Exception e) {
|
||||
errorLogger.error(e, ErrorContext.builder().related(event).build());
|
||||
}
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onMove(MoveEntityEvent event, @First Player player) {
|
||||
public void onMove(MoveEntityEvent event, @First ServerPlayer player) {
|
||||
performedAction(player);
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onPlayerChat(MessageChannelEvent.Chat event, @First Player player) {
|
||||
public void onPlayerChat(PlayerChatEvent event, @First ServerPlayer player) {
|
||||
performedAction(player);
|
||||
}
|
||||
|
||||
private void performedAction(Player player) {
|
||||
UUID uuid = player.getUniqueId();
|
||||
private void performedAction(ServerPlayer player) {
|
||||
UUID uuid = player.uniqueId();
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
boolean ignored = ignorePermissionInfo.computeIfAbsent(uuid, keyUUID -> player.hasPermission(Permissions.IGNORE_AFK.getPermission()));
|
||||
@ -102,22 +102,22 @@ public class SpongeAFKListener {
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onPlayerCommand(SendCommandEvent event, @First Player player) {
|
||||
public void onPlayerCommand(ExecuteCommandEvent event, @First ServerPlayer player) {
|
||||
performedAction(player);
|
||||
|
||||
boolean isAfkCommand = event.getCommand().toLowerCase().startsWith("afk");
|
||||
boolean isAfkCommand = event.command().toLowerCase().startsWith("afk");
|
||||
if (isAfkCommand) {
|
||||
afkTracker.usedAfkCommand(player.getUniqueId(), System.currentTimeMillis());
|
||||
afkTracker.usedAfkCommand(player.uniqueId(), System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onSettingsChange(PlayerChangeClientSettingsEvent event) {
|
||||
event(event);
|
||||
event(event, event.player());
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onLeave(ClientConnectionEvent.Disconnect event) {
|
||||
ignorePermissionInfo.remove(event.getTargetEntity().getUniqueId());
|
||||
public void onLeave(ServerSideConnectionEvent.Disconnect event) {
|
||||
ignorePermissionInfo.remove(event.player().uniqueId());
|
||||
}
|
||||
}
|
@ -23,11 +23,12 @@ import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.transactions.events.NicknameStoreTransaction;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorContext;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorLogger;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.Order;
|
||||
import org.spongepowered.api.event.filter.cause.First;
|
||||
import org.spongepowered.api.event.message.MessageChannelEvent;
|
||||
import org.spongepowered.api.event.message.PlayerChatEvent;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.UUID;
|
||||
@ -58,11 +59,7 @@ public class SpongeChatListener {
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onPlayerChat(MessageChannelEvent.Chat event, @First Player player) {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
public void onPlayerChat(PlayerChatEvent event, @First Player player) {
|
||||
try {
|
||||
actOnChatEvent(player);
|
||||
} catch (Exception e) {
|
||||
@ -72,8 +69,8 @@ public class SpongeChatListener {
|
||||
|
||||
private void actOnChatEvent(@First Player player) {
|
||||
long time = System.currentTimeMillis();
|
||||
UUID uuid = player.getUniqueId();
|
||||
String displayName = player.getDisplayNameData().displayName().get().toPlain();
|
||||
UUID uuid = player.uniqueId();
|
||||
String displayName = LegacyComponentSerializer.legacySection().serialize(player.displayName().get());
|
||||
|
||||
dbSystem.getDatabase().executeTransaction(new NicknameStoreTransaction(
|
||||
uuid, new Nickname(displayName, time, serverInfo.getServerUUID()),
|
||||
|
@ -27,27 +27,28 @@ import com.djrapitops.plan.processing.processors.player.MobKillProcessor;
|
||||
import com.djrapitops.plan.processing.processors.player.PlayerKillProcessor;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorContext;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorLogger;
|
||||
import org.spongepowered.api.ResourceKey;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.data.key.Keys;
|
||||
import org.spongepowered.api.data.type.HandTypes;
|
||||
import org.spongepowered.api.entity.EnderCrystal;
|
||||
import org.spongepowered.api.data.value.Value;
|
||||
import org.spongepowered.api.entity.Entity;
|
||||
import org.spongepowered.api.entity.explosive.EndCrystal;
|
||||
import org.spongepowered.api.entity.living.Living;
|
||||
import org.spongepowered.api.entity.living.animal.Wolf;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.entity.projectile.Projectile;
|
||||
import org.spongepowered.api.entity.projectile.source.ProjectileSource;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.cause.entity.damage.source.EntityDamageSource;
|
||||
import org.spongepowered.api.event.entity.DestructEntityEvent;
|
||||
import org.spongepowered.api.item.ItemType;
|
||||
import org.spongepowered.api.item.ItemTypes;
|
||||
import org.spongepowered.api.item.inventory.ItemStack;
|
||||
import org.spongepowered.api.projectile.source.ProjectileSource;
|
||||
import org.spongepowered.api.registry.RegistryTypes;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Listener for Deaths and Kills on Sponge.
|
||||
@ -74,24 +75,24 @@ public class SpongeDeathListener {
|
||||
@Listener
|
||||
public void onEntityDeath(DestructEntityEvent.Death event) {
|
||||
long time = System.currentTimeMillis();
|
||||
Living dead = event.getTargetEntity();
|
||||
Living dead = event.entity();
|
||||
|
||||
if (dead instanceof Player) {
|
||||
// Process Death
|
||||
SessionCache.getCachedSession(dead.getUniqueId()).ifPresent(ActiveSession::addDeath);
|
||||
SessionCache.getCachedSession(dead.uniqueId()).ifPresent(ActiveSession::addDeath);
|
||||
}
|
||||
|
||||
try {
|
||||
List<EntityDamageSource> causes = event.getCause().allOf(EntityDamageSource.class);
|
||||
List<EntityDamageSource> causes = event.cause().allOf(EntityDamageSource.class);
|
||||
Optional<Player> foundKiller = findKiller(causes, 0);
|
||||
if (!foundKiller.isPresent()) {
|
||||
if (foundKiller.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Player killer = foundKiller.get();
|
||||
|
||||
Runnable processor = dead instanceof Player
|
||||
? new PlayerKillProcessor(getKiller(killer), getVictim((Player) dead), serverInfo.getServerIdentifier(), findWeapon(event), time)
|
||||
: new MobKillProcessor(killer.getUniqueId());
|
||||
: new MobKillProcessor(killer.uniqueId());
|
||||
processing.submitCritical(processor);
|
||||
} catch (Exception e) {
|
||||
errorLogger.error(e, ErrorContext.builder().related(event, dead).build());
|
||||
@ -99,11 +100,11 @@ public class SpongeDeathListener {
|
||||
}
|
||||
|
||||
private PlayerKill.Killer getKiller(Player killer) {
|
||||
return new PlayerKill.Killer(killer.getUniqueId(), killer.getName());
|
||||
return new PlayerKill.Killer(killer.uniqueId(), killer.name());
|
||||
}
|
||||
|
||||
private PlayerKill.Victim getVictim(Player victim) {
|
||||
return new PlayerKill.Victim(victim.getUniqueId(), victim.getName());
|
||||
return new PlayerKill.Victim(victim.uniqueId(), victim.name());
|
||||
}
|
||||
|
||||
public Optional<Player> findKiller(List<EntityDamageSource> causes, int depth) {
|
||||
@ -112,40 +113,41 @@ public class SpongeDeathListener {
|
||||
}
|
||||
|
||||
EntityDamageSource damageSource = causes.get(depth);
|
||||
Entity killerEntity = damageSource.getSource();
|
||||
Entity killerEntity = damageSource.source();
|
||||
|
||||
if (killerEntity instanceof Player) return Optional.of((Player) killerEntity);
|
||||
if (killerEntity instanceof Wolf) return getOwner((Wolf) killerEntity);
|
||||
if (killerEntity instanceof Projectile) return getShooter((Projectile) killerEntity);
|
||||
if (killerEntity instanceof EnderCrystal) return findKiller(causes, depth + 1);
|
||||
if (killerEntity instanceof EndCrystal) return findKiller(causes, depth + 1);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public String findWeapon(DestructEntityEvent.Death death) {
|
||||
Optional<EntityDamageSource> damagedBy = death.getCause().first(EntityDamageSource.class);
|
||||
Optional<EntityDamageSource> damagedBy = death.cause().first(EntityDamageSource.class);
|
||||
if (damagedBy.isPresent()) {
|
||||
EntityDamageSource damageSource = damagedBy.get();
|
||||
Entity killerEntity = damageSource.getSource();
|
||||
Entity killerEntity = damageSource.source();
|
||||
|
||||
if (killerEntity instanceof Player) return getItemInHand((Player) killerEntity);
|
||||
if (killerEntity instanceof Wolf) return "Wolf";
|
||||
|
||||
return new EntityNameFormatter().apply(killerEntity.getType().getName());
|
||||
Optional<ResourceKey> entityType = killerEntity.type().findKey(RegistryTypes.ENTITY_TYPE);
|
||||
if (entityType.isPresent()) {
|
||||
return new EntityNameFormatter().apply(entityType.get().value());
|
||||
}
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
private String getItemInHand(Player killer) {
|
||||
Optional<ItemStack> inMainHand = killer.getItemInHand(HandTypes.MAIN_HAND);
|
||||
ItemStack inHand = inMainHand.orElse(
|
||||
killer.getItemInHand(HandTypes.OFF_HAND)
|
||||
.orElse(ItemStack.empty()));
|
||||
ItemType type = inHand.isEmpty() ? ItemTypes.AIR : inHand.getType();
|
||||
return new ItemNameFormatter().apply(type.getName());
|
||||
ItemStack inMainHand = killer.itemInHand(HandTypes.MAIN_HAND);
|
||||
ItemStack inHand = inMainHand.isEmpty() ? killer.itemInHand(HandTypes.OFF_HAND) : inMainHand;
|
||||
ItemType type = inHand.isEmpty() ? ItemTypes.AIR.get() : inHand.type();
|
||||
return new ItemNameFormatter().apply(type.key(RegistryTypes.ITEM_TYPE).value());
|
||||
}
|
||||
|
||||
private Optional<Player> getShooter(Projectile projectile) {
|
||||
ProjectileSource source = projectile.getShooter();
|
||||
ProjectileSource source = projectile.shooter().map(Value::get).orElse(null);
|
||||
if (source instanceof Player) {
|
||||
return Optional.of((Player) source);
|
||||
}
|
||||
@ -154,10 +156,6 @@ public class SpongeDeathListener {
|
||||
}
|
||||
|
||||
private Optional<Player> getOwner(Wolf wolf) {
|
||||
Optional<Optional<UUID>> isTamed = wolf.get(Keys.TAMED_OWNER);
|
||||
if (!isTamed.isPresent()) return Optional.empty();
|
||||
Optional<UUID> owner = isTamed.get();
|
||||
|
||||
return owner.flatMap(Sponge.getGame().getServer()::getPlayer);
|
||||
return wolf.tamer().flatMap(uuid -> Sponge.game().server().player(uuid.get()));
|
||||
}
|
||||
}
|
@ -24,14 +24,21 @@ import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.transactions.events.WorldNameStoreTransaction;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorContext;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorLogger;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.Order;
|
||||
import org.spongepowered.api.event.entity.living.humanoid.ChangeGameModeEvent;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import org.spongepowered.api.ResourceKey;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.entity.living.player.gamemode.GameMode;
|
||||
import org.spongepowered.api.entity.living.player.gamemode.GameModes;
|
||||
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
|
||||
import org.spongepowered.api.registry.RegistryTypes;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Listener for GameMode change on Sponge.
|
||||
@ -40,6 +47,8 @@ import java.util.UUID;
|
||||
*/
|
||||
public class SpongeGMChangeListener {
|
||||
|
||||
public static final List<Consumer<Event>> EVENT_CONSUMERS = new ArrayList<>(); // Available to the mixin
|
||||
|
||||
private final WorldAliasSettings worldAliasSettings;
|
||||
private final ServerInfo serverInfo;
|
||||
private final DBSystem dbSystem;
|
||||
@ -56,34 +65,71 @@ public class SpongeGMChangeListener {
|
||||
this.serverInfo = serverInfo;
|
||||
this.dbSystem = dbSystem;
|
||||
this.errorLogger = errorLogger;
|
||||
EVENT_CONSUMERS.add(this::onMixin);
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onGMChange(ChangeGameModeEvent.TargetPlayer event) {
|
||||
if (event.isCancelled()) {
|
||||
public static class Event {
|
||||
private final Player player;
|
||||
private final GameType gameType;
|
||||
|
||||
public Event(Player player, GameType gameType) {
|
||||
this.player = player;
|
||||
this.gameType = gameType;
|
||||
}
|
||||
}
|
||||
|
||||
private void onMixin(Event event) {
|
||||
ServerPlayer serverPlayer = Sponge.game().server()
|
||||
.player(event.player.getUUID())
|
||||
.orElse(null);
|
||||
if (serverPlayer == null) {
|
||||
// uh oh
|
||||
errorLogger.error(
|
||||
new RuntimeException("GameMode changed for player but no ServerPlayer was found"),
|
||||
ErrorContext.builder()
|
||||
.related(event.player, event.player.getGameProfile().getName())
|
||||
.whatToDo("Report this, the gamemode change mixin might be broken")
|
||||
.build()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
actOnGMChangeEvent(event);
|
||||
} catch (Exception e) {
|
||||
errorLogger.error(e, ErrorContext.builder().related(event, event.getGameMode()).build());
|
||||
}
|
||||
GameMode gameMode = GameModes.registry().value(ResourceKey.sponge(event.gameType.getName()));
|
||||
actOnGMChangeEvent(serverPlayer, gameMode);
|
||||
}
|
||||
|
||||
private void actOnGMChangeEvent(ChangeGameModeEvent.TargetPlayer event) {
|
||||
Player player = event.getTargetEntity();
|
||||
UUID uuid = player.getUniqueId();
|
||||
// This listener can replace the mixin if this pr is merged:
|
||||
// https://github.com/SpongePowered/Sponge/pull/3563
|
||||
|
||||
// @Listener(order = Order.POST)
|
||||
// public void onGMChange(ChangeDataHolderEvent.ValueChange event) {
|
||||
// ServerPlayer player = event.targetHolder() instanceof ServerPlayer ? (ServerPlayer) event.targetHolder() : null;
|
||||
// if (player == null) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// DataTransactionResult result = event.endResult();
|
||||
// Optional<Value.Immutable<GameMode>> gameModeValue = result.successfulValue(Keys.GAME_MODE);
|
||||
// if (gameModeValue.isEmpty()) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// GameMode newMode = gameModeValue.get().get();
|
||||
// actOnGMChangeEvent(player, newMode);
|
||||
// }
|
||||
|
||||
private void actOnGMChangeEvent(ServerPlayer player, GameMode gameMode) {
|
||||
UUID uuid = player.uniqueId();
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
String gameMode = event.getGameMode().getName().toUpperCase();
|
||||
String worldName = player.getWorld().getName();
|
||||
String gameModeText = gameMode.key(RegistryTypes.GAME_MODE).value().toUpperCase();
|
||||
String worldName = Sponge.game().server().worldManager().worldDirectory(player.world().key())
|
||||
.map(path -> path.getFileName().toString()).orElse("Unknown");
|
||||
|
||||
dbSystem.getDatabase().executeTransaction(new WorldNameStoreTransaction(serverInfo.getServerUUID(), worldName));
|
||||
worldAliasSettings.addWorld(worldName);
|
||||
|
||||
Optional<ActiveSession> cachedSession = SessionCache.getCachedSession(uuid);
|
||||
cachedSession.ifPresent(session -> session.changeState(worldName, gameMode, time));
|
||||
cachedSession.ifPresent(session -> session.changeState(worldName, gameModeText, time));
|
||||
}
|
||||
|
||||
}
|
@ -24,13 +24,14 @@ import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.transactions.events.WorldNameStoreTransaction;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorContext;
|
||||
import com.djrapitops.plan.utilities.logging.ErrorLogger;
|
||||
import org.spongepowered.api.data.key.Keys;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.entity.living.player.gamemode.GameMode;
|
||||
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
|
||||
import org.spongepowered.api.event.Listener;
|
||||
import org.spongepowered.api.event.Order;
|
||||
import org.spongepowered.api.event.entity.MoveEntityEvent;
|
||||
import org.spongepowered.api.event.entity.ChangeEntityWorldEvent;
|
||||
import org.spongepowered.api.event.filter.cause.First;
|
||||
import org.spongepowered.api.registry.RegistryTypes;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Optional;
|
||||
@ -62,11 +63,7 @@ public class SpongeWorldChangeListener {
|
||||
}
|
||||
|
||||
@Listener(order = Order.POST)
|
||||
public void onWorldChange(MoveEntityEvent.Teleport event, @First Player player) {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
public void onWorldChange(ChangeEntityWorldEvent event, @First ServerPlayer player) {
|
||||
try {
|
||||
actOnEvent(event, player);
|
||||
} catch (Exception e) {
|
||||
@ -74,12 +71,13 @@ public class SpongeWorldChangeListener {
|
||||
}
|
||||
}
|
||||
|
||||
private void actOnEvent(MoveEntityEvent.Teleport event, Player player) {
|
||||
private void actOnEvent(ChangeEntityWorldEvent event, ServerPlayer player) {
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
UUID uuid = player.getUniqueId();
|
||||
UUID uuid = player.uniqueId();
|
||||
|
||||
String worldName = event.getToTransform().getExtent().getName();
|
||||
String worldName = Sponge.game().server().worldManager().worldDirectory(event.destinationWorld().key())
|
||||
.map(path -> path.getFileName().toString()).orElse("Unknown");
|
||||
String gameMode = getGameMode(player);
|
||||
|
||||
dbSystem.getDatabase().executeTransaction(new WorldNameStoreTransaction(serverInfo.getServerUUID(), worldName));
|
||||
@ -89,9 +87,9 @@ public class SpongeWorldChangeListener {
|
||||
cachedSession.ifPresent(session -> session.changeState(worldName, gameMode, time));
|
||||
}
|
||||
|
||||
private String getGameMode(Player player) {
|
||||
Optional<GameMode> gameMode = player.getGameModeData().get(Keys.GAME_MODE);
|
||||
return gameMode.map(gm -> gm.getName().toUpperCase()).orElse("ADVENTURE");
|
||||
private String getGameMode(ServerPlayer player) {
|
||||
GameMode gameMode = player.gameMode().get();
|
||||
return gameMode.key(RegistryTypes.GAME_MODE).value().toUpperCase();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of Player Analytics (Plan).
|
||||
*
|
||||
* Plan is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License v3 as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Plan 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.djrapitops.plan.gathering.mixin;
|
||||
|
||||
import com.djrapitops.plan.gathering.listeners.sponge.SpongeGMChangeListener;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ServerPlayer.class)
|
||||
public class GameModeChangeMixin {
|
||||
|
||||
@Inject(method = "setGameMode", at = @At("HEAD"))
|
||||
private void onGameModeChange(GameType gameType, CallbackInfo ci) {
|
||||
SpongeGMChangeListener.Event event = new SpongeGMChangeListener.Event((Player) (Object) this, gameType);
|
||||
SpongeGMChangeListener.EVENT_CONSUMERS.forEach(consumer -> consumer.accept(event));
|
||||
}
|
||||
}
|
@ -36,8 +36,9 @@ import net.playeranalytics.plugin.scheduling.TimeAmount;
|
||||
import net.playeranalytics.plugin.server.Listeners;
|
||||
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.event.Listener;
|
||||
import org.spongepowered.api.event.network.ClientConnectionEvent;
|
||||
import org.spongepowered.api.event.network.ServerSideConnectionEvent;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.*;
|
||||
@ -93,7 +94,7 @@ public class SpongePingCounter extends TaskSystem.Task {
|
||||
Map.Entry<UUID, List<DateObj<Integer>>> entry = iterator.next();
|
||||
UUID uuid = entry.getKey();
|
||||
List<DateObj<Integer>> history = entry.getValue();
|
||||
Optional<Player> player = Sponge.getServer().getPlayer(uuid);
|
||||
Optional<ServerPlayer> player = Sponge.server().player(uuid);
|
||||
if (player.isPresent()) {
|
||||
int ping = getPing(player.get());
|
||||
if (ping <= -1 || ping > TimeUnit.SECONDS.toMillis(8L)) {
|
||||
@ -129,27 +130,27 @@ public class SpongePingCounter extends TaskSystem.Task {
|
||||
}
|
||||
|
||||
public void removePlayer(Player player) {
|
||||
playerHistory.remove(player.getUniqueId());
|
||||
startRecording.remove(player.getUniqueId());
|
||||
playerHistory.remove(player.uniqueId());
|
||||
startRecording.remove(player.uniqueId());
|
||||
}
|
||||
|
||||
private int getPing(Player player) {
|
||||
return player.getConnection().getLatency();
|
||||
private int getPing(ServerPlayer player) {
|
||||
return player.connection().latency();
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onPlayerJoin(ClientConnectionEvent.Join joinEvent) {
|
||||
Player player = joinEvent.getTargetEntity();
|
||||
public void onPlayerJoin(ServerSideConnectionEvent.Join joinEvent) {
|
||||
Player player = joinEvent.player();
|
||||
Long pingDelayMs = config.get(TimeSettings.PING_PLAYER_LOGIN_DELAY);
|
||||
if (pingDelayMs >= TimeUnit.HOURS.toMillis(2L)) {
|
||||
return;
|
||||
}
|
||||
startRecording.put(player.getUniqueId(), System.currentTimeMillis() + pingDelayMs);
|
||||
startRecording.put(player.uniqueId(), System.currentTimeMillis() + pingDelayMs);
|
||||
}
|
||||
|
||||
@Listener
|
||||
public void onPlayerQuit(ClientConnectionEvent.Disconnect quitEvent) {
|
||||
removePlayer(quitEvent.getTargetEntity());
|
||||
public void onPlayerQuit(ServerSideConnectionEvent.Disconnect quitEvent) {
|
||||
removePlayer(quitEvent.player());
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
|
@ -32,15 +32,16 @@ public class SpongeServerProperties extends ServerProperties {
|
||||
|
||||
@Inject
|
||||
public SpongeServerProperties(Game game) {
|
||||
// Port and max players cannot be provided as Game#server will fail when this is called (ConstructPluginEvent)
|
||||
super(
|
||||
"Sponge",
|
||||
game.getServer().getBoundAddress().orElseGet(() -> new InetSocketAddress(25565)).getPort(),
|
||||
game.getPlatform().getMinecraftVersion().getName(),
|
||||
game.getPlatform().getMinecraftVersion().getName(),
|
||||
() -> game.getServer().getBoundAddress()
|
||||
-1, //game.server().boundAddress().orElseGet(() -> new InetSocketAddress(25565)).getPort(),
|
||||
game.platform().minecraftVersion().name(),
|
||||
game.platform().minecraftVersion().name(),
|
||||
() -> game.server().boundAddress()
|
||||
.orElseGet(() -> new InetSocketAddress(25565))
|
||||
.getAddress().getHostAddress(),
|
||||
game.getServer().getMaxPlayers()
|
||||
-1 //game.server().maxPlayers()
|
||||
);
|
||||
}
|
||||
}
|
@ -34,7 +34,7 @@ import com.djrapitops.plan.version.SpongeVersionChecker;
|
||||
import com.djrapitops.plan.version.VersionChecker;
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import org.spongepowered.api.world.World;
|
||||
import org.spongepowered.api.world.server.ServerWorld;
|
||||
|
||||
/**
|
||||
* Module for binding Sponge specific classes as interface implementations.
|
||||
@ -63,10 +63,10 @@ public interface SpongeSuperClassBindingModule {
|
||||
ServerShutdownSave bindServerShutdownSave(SpongeServerShutdownSave shutdownSave);
|
||||
|
||||
@Binds
|
||||
ServerSensor<World> bindServerSensor(SpongeSensor sensor);
|
||||
ServerSensor<ServerWorld> bindServerSensor(SpongeSensor sensor);
|
||||
|
||||
@Binds
|
||||
ServerSensor<?> bindGenericsServerSensor(ServerSensor<World> sensor);
|
||||
ServerSensor<?> bindGenericsServerSensor(ServerSensor<ServerWorld> sensor);
|
||||
|
||||
@Binds
|
||||
VersionChecker bindVersionChecker(SpongeVersionChecker versionChecker);
|
||||
|
@ -35,13 +35,14 @@ import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.multibindings.IntoSet;
|
||||
import org.spongepowered.api.world.World;
|
||||
import org.spongepowered.api.world.server.ServerWorld;
|
||||
|
||||
@Module
|
||||
public interface SpongeTaskModule {
|
||||
|
||||
@Binds
|
||||
@IntoSet
|
||||
TaskSystem.Task bindTPSCounter(ServerTPSCounter<World> tpsCounter);
|
||||
TaskSystem.Task bindTPSCounter(ServerTPSCounter<ServerWorld> tpsCounter);
|
||||
|
||||
@Binds
|
||||
@IntoSet
|
||||
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* This file is part of Player Analytics (Plan).
|
||||
*
|
||||
* Plan is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License v3 as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Plan 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.djrapitops.plan.storage.file;
|
||||
|
||||
import org.spongepowered.api.asset.Asset;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@link Resource} implementation for Sponge Asset API.
|
||||
*
|
||||
* @author AuroraLS3
|
||||
*/
|
||||
public class SpongeAssetResource implements Resource {
|
||||
|
||||
private final String resourceName;
|
||||
private final Asset asset;
|
||||
|
||||
public SpongeAssetResource(String resourceName, Asset asset) {
|
||||
this.resourceName = resourceName;
|
||||
this.asset = asset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResourceName() {
|
||||
return resourceName;
|
||||
}
|
||||
|
||||
private void nullCheck() throws FileNotFoundException {
|
||||
if (asset == null) {
|
||||
throw new FileNotFoundException("a Resource was not found inside the jar (/assets/plan/" + resourceName + "), " +
|
||||
"Plan does not support /reload or updates using " +
|
||||
"Plugin Managers, restart the server and see if the error persists.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream asInputStream() throws IOException {
|
||||
nullCheck();
|
||||
return new ByteArrayInputStream(asset.readBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> asLines() throws IOException {
|
||||
return asset.readLines(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() throws IOException {
|
||||
return asset.readString(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] asBytes() throws IOException {
|
||||
return asset.readBytes();
|
||||
}
|
||||
}
|
@ -17,14 +17,18 @@
|
||||
package com.djrapitops.plan.storage.file;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.PlanSponge;
|
||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||
import dagger.Lazy;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.resource.ResourcePath;
|
||||
import org.spongepowered.plugin.PluginContainer;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.File;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Implements jar resource fetching with Sponge Asset API.
|
||||
@ -50,9 +54,26 @@ public class SpongePlanFiles extends PlanFiles {
|
||||
@Override
|
||||
public Resource getResourceFromJar(String resourceName) {
|
||||
try {
|
||||
return new SpongeAssetResource(resourceName, Sponge.getAssetManager().getAsset(plugin, resourceName).orElse(null));
|
||||
} catch (IllegalStateException spongeNotEnabled) {
|
||||
if (!(plugin instanceof PlanSponge)) {
|
||||
throw new IllegalStateException("Not a Sponge plugin");
|
||||
}
|
||||
PluginContainer container = ((PlanSponge) plugin).getPlugin();
|
||||
ResourcePath resourcePath = ResourcePath.of(container, resourceName);
|
||||
org.spongepowered.api.resource.Resource resource = Sponge.server().resourceManager().load(resourcePath);
|
||||
|
||||
return asStringResource(resource, resourceName);
|
||||
} catch (IllegalStateException | IOException ignored) {
|
||||
return super.getResourceFromJar(resourceName);
|
||||
}
|
||||
}
|
||||
|
||||
private Resource asStringResource(org.spongepowered.api.resource.Resource resource, String resourceName) throws IOException {
|
||||
try (
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(resource.inputStream(), StandardCharsets.UTF_8));
|
||||
StringWriter writer = new StringWriter()
|
||||
) {
|
||||
reader.transferTo(writer);
|
||||
return new StringResource(resourceName, writer.toString());
|
||||
}
|
||||
}
|
||||
}
|
8
Plan/sponge/src/main/resources/plan-sponge.mixins.json
Normal file
8
Plan/sponge/src/main/resources/plan-sponge.mixins.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"required": true,
|
||||
"package": "com.djrapitops.plan.gathering.mixin",
|
||||
"minVersion": "0.7.11",
|
||||
"mixins": [
|
||||
"GameModeChangeMixin"
|
||||
]
|
||||
}
|
@ -16,18 +16,18 @@
|
||||
*/
|
||||
package utilities.mocks;
|
||||
|
||||
import com.djrapitops.plan.DaggerPlanSpongeComponent;
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.PlanSpongeComponent;
|
||||
import com.djrapitops.plan.PlanSystem;
|
||||
import com.djrapitops.plan.DaggerPlanSpongeComponent;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import com.djrapitops.plan.storage.database.SQLDB;
|
||||
import org.mockito.Mockito;
|
||||
import org.spongepowered.api.Game;
|
||||
import org.spongepowered.api.MinecraftVersion;
|
||||
import org.spongepowered.api.Platform;
|
||||
import org.spongepowered.api.Server;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.text.Text;
|
||||
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.file.Path;
|
||||
@ -81,8 +81,8 @@ public class SpongeMockComponent {
|
||||
|
||||
Platform platform = mockPlatform();
|
||||
Server server = mockServer();
|
||||
doReturn(platform).when(game).getPlatform();
|
||||
doReturn(server).when(game).getServer();
|
||||
doReturn(platform).when(game).platform();
|
||||
doReturn(server).when(game).server();
|
||||
|
||||
return game;
|
||||
}
|
||||
@ -91,8 +91,8 @@ public class SpongeMockComponent {
|
||||
Platform platform = Mockito.mock(Platform.class);
|
||||
|
||||
MinecraftVersion version = Mockito.mock(MinecraftVersion.class);
|
||||
doReturn("1.12").when(version).getName();
|
||||
doReturn(version).when(platform).getMinecraftVersion();
|
||||
doReturn("1.12").when(version).name();
|
||||
doReturn(version).when(platform).minecraftVersion();
|
||||
|
||||
return platform;
|
||||
}
|
||||
@ -100,16 +100,16 @@ public class SpongeMockComponent {
|
||||
private Server mockServer() {
|
||||
Server server = Mockito.mock(Server.class);
|
||||
|
||||
Text motd = Mockito.mock(Text.class);
|
||||
doReturn("Motd").when(motd).toPlain();
|
||||
TextComponent motd = Mockito.mock(TextComponent.class);
|
||||
doReturn("Motd").when(motd).content();
|
||||
Optional<InetSocketAddress> ip = Optional.of(new InetSocketAddress(25565));
|
||||
int maxPlayers = 20;
|
||||
List<Player> online = new ArrayList<>();
|
||||
List<ServerPlayer> online = new ArrayList<>();
|
||||
|
||||
doReturn(motd).when(server).getMotd();
|
||||
doReturn(ip).when(server).getBoundAddress();
|
||||
doReturn(maxPlayers).when(server).getMaxPlayers();
|
||||
doReturn(online).when(server).getOnlinePlayers();
|
||||
doReturn(motd).when(server).motd();
|
||||
doReturn(ip).when(server).boundAddress();
|
||||
doReturn(maxPlayers).when(server).maxPlayers();
|
||||
doReturn(online).when(server).onlinePlayers();
|
||||
|
||||
return server;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public class VelocityCMDSender implements CMDSender {
|
||||
|
||||
@Override
|
||||
public MessageBuilder buildMessage() {
|
||||
return new VelocityMessageBuilder(this);
|
||||
return new AdventureMessageBuilder(this, commandSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user