aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spark-bukkit/build.gradle4
-rw-r--r--spark-bukkit/src/main/java/me/lucko/spark/bukkit/BukkitCommandSender.java61
-rw-r--r--spark-bukkit/src/main/java/me/lucko/spark/bukkit/SparkBukkitPlugin.java39
-rw-r--r--spark-bungeecord/build.gradle4
-rw-r--r--spark-bungeecord/src/main/java/me/lucko/spark/bungeecord/BungeeCordCommandSender.java61
-rw-r--r--spark-bungeecord/src/main/java/me/lucko/spark/bungeecord/SparkBungeeCordPlugin.java42
-rw-r--r--spark-common/build.gradle11
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/ActivityLog.java195
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/CommandSender.java33
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/SparkPlatform.java84
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/SparkPlugin.java7
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/command/Command.java45
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/command/CommandModule.java4
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/command/CommandResponseHandler.java22
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/command/modules/ActivityLogModule.java120
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/command/modules/HealthModule.java30
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/command/modules/MemoryModule.java11
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/command/modules/SamplerModule.java11
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/command/modules/TickMonitoringModule.java10
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/monitor/tick/TickMonitor.java12
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/monitor/tick/TpsCalculator.java2
-rw-r--r--spark-forge/build.gradle6
-rw-r--r--spark-forge/src/main/java/me/lucko/spark/forge/ForgeClientSparkPlugin.java16
-rw-r--r--spark-forge/src/main/java/me/lucko/spark/forge/ForgeCommandSender.java66
-rw-r--r--spark-forge/src/main/java/me/lucko/spark/forge/ForgeServerSparkPlugin.java20
-rw-r--r--spark-forge/src/main/java/me/lucko/spark/forge/ForgeSparkPlugin.java45
-rw-r--r--spark-sponge/build.gradle4
-rw-r--r--spark-sponge/src/main/java/me/lucko/spark/sponge/SparkSpongePlugin.java36
-rw-r--r--spark-sponge/src/main/java/me/lucko/spark/sponge/SpongeCommandSender.java62
-rw-r--r--spark-velocity/src/main/java/me/lucko/spark/velocity/SparkVelocityPlugin.java36
-rw-r--r--spark-velocity/src/main/java/me/lucko/spark/velocity/VelocityCommandSender.java69
31 files changed, 903 insertions, 265 deletions
diff --git a/spark-bukkit/build.gradle b/spark-bukkit/build.gradle
index e8c6721..836e389 100644
--- a/spark-bukkit/build.gradle
+++ b/spark-bukkit/build.gradle
@@ -1,6 +1,8 @@
dependencies {
compile project(':spark-common')
- compile 'net.kyori:text-adapter-bukkit:1.0.3'
+ compile('net.kyori:text-adapter-bukkit:1.0.3') {
+ exclude(module: 'text')
+ }
compileOnly 'org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT'
}
diff --git a/spark-bukkit/src/main/java/me/lucko/spark/bukkit/BukkitCommandSender.java b/spark-bukkit/src/main/java/me/lucko/spark/bukkit/BukkitCommandSender.java
new file mode 100644
index 0000000..dacea76
--- /dev/null
+++ b/spark-bukkit/src/main/java/me/lucko/spark/bukkit/BukkitCommandSender.java
@@ -0,0 +1,61 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.bukkit;
+
+import me.lucko.spark.common.CommandSender;
+import net.kyori.text.Component;
+import net.kyori.text.adapter.bukkit.TextAdapter;
+
+public class BukkitCommandSender implements CommandSender {
+ private final org.bukkit.command.CommandSender sender;
+
+ public BukkitCommandSender(org.bukkit.command.CommandSender sender) {
+ this.sender = sender;
+ }
+
+ @Override
+ public String getName() {
+ return this.sender.getName();
+ }
+
+ @Override
+ public void sendMessage(Component message) {
+ TextAdapter.sendComponent(this.sender, message);
+ }
+
+ @Override
+ public boolean hasPermission(String permission) {
+ return this.sender.hasPermission(permission);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ BukkitCommandSender that = (BukkitCommandSender) o;
+ return this.sender.equals(that.sender);
+ }
+
+ @Override
+ public int hashCode() {
+ return this.sender.hashCode();
+ }
+}
diff --git a/spark-bukkit/src/main/java/me/lucko/spark/bukkit/SparkBukkitPlugin.java b/spark-bukkit/src/main/java/me/lucko/spark/bukkit/SparkBukkitPlugin.java
index 15c725d..ee85c70 100644
--- a/spark-bukkit/src/main/java/me/lucko/spark/bukkit/SparkBukkitPlugin.java
+++ b/spark-bukkit/src/main/java/me/lucko/spark/bukkit/SparkBukkitPlugin.java
@@ -20,29 +20,27 @@
package me.lucko.spark.bukkit;
+import me.lucko.spark.common.CommandSender;
import me.lucko.spark.common.SparkPlatform;
import me.lucko.spark.common.SparkPlugin;
import me.lucko.spark.common.command.CommandResponseHandler;
import me.lucko.spark.common.monitor.tick.TpsCalculator;
import me.lucko.spark.common.sampler.ThreadDumper;
import me.lucko.spark.common.sampler.TickCounter;
-import net.kyori.text.Component;
import net.kyori.text.TextComponent;
-import net.kyori.text.adapter.bukkit.TextAdapter;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
-import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
import java.nio.file.Path;
-import java.util.Collections;
-import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
-public class SparkBukkitPlugin extends JavaPlugin implements SparkPlugin<CommandSender> {
+public class SparkBukkitPlugin extends JavaPlugin implements SparkPlugin {
- private final SparkPlatform<CommandSender> platform = new SparkPlatform<>(this);
+ private final SparkPlatform platform = new SparkPlatform(this);
@Override
public void onEnable() {
@@ -56,7 +54,7 @@ public class SparkBukkitPlugin extends JavaPlugin implements SparkPlugin<Command
return true;
}
- CommandResponseHandler<CommandSender> resp = new CommandResponseHandler<>(this.platform, sender);
+ CommandResponseHandler resp = new CommandResponseHandler(this.platform, new BukkitCommandSender(sender));
TpsCalculator tpsCalculator = this.platform.getTpsCalculator();
resp.replyPrefixed(TextComponent.of("TPS from last 5s, 10s, 1m, 5m, 15m:"));
resp.replyPrefixed(TextComponent.builder(" ").append(tpsCalculator.toFormattedComponent()).build());
@@ -71,22 +69,14 @@ public class SparkBukkitPlugin extends JavaPlugin implements SparkPlugin<Command
}
@Override
- public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
- if (!sender.hasPermission("spark")) {
- sender.sendMessage(ChatColor.RED + "You do not have permission to use this command.");
- return true;
- }
-
- this.platform.executeCommand(sender, args);
+ public boolean onCommand(org.bukkit.command.CommandSender sender, Command command, String label, String[] args) {
+ this.platform.executeCommand(new BukkitCommandSender(sender), args);
return true;
}
@Override
- public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
- if (!sender.hasPermission("spark")) {
- return Collections.emptyList();
- }
- return this.platform.tabCompleteCommand(sender, args);
+ public List<String> onTabComplete(org.bukkit.command.CommandSender sender, Command command, String alias, String[] args) {
+ return this.platform.tabCompleteCommand(new BukkitCommandSender(sender), args);
}
@Override
@@ -106,15 +96,10 @@ public class SparkBukkitPlugin extends JavaPlugin implements SparkPlugin<Command
@Override
public Set<CommandSender> getSendersWithPermission(String permission) {
- Set<CommandSender> senders = new HashSet<>(getServer().getOnlinePlayers());
+ List<org.bukkit.command.CommandSender> senders = new LinkedList<>(getServer().getOnlinePlayers());
senders.removeIf(sender -> !sender.hasPermission(permission));
senders.add(getServer().getConsoleSender());
- return senders;
- }
-
- @Override
- public void sendMessage(CommandSender sender, Component message) {
- TextAdapter.sendComponent(sender, message);
+ return senders.stream().map(BukkitCommandSender::new).collect(Collectors.toSet());
}
@Override
diff --git a/spark-bungeecord/build.gradle b/spark-bungeecord/build.gradle
index 55dcb4e..5ee50d7 100644
--- a/spark-bungeecord/build.gradle
+++ b/spark-bungeecord/build.gradle
@@ -1,6 +1,8 @@
dependencies {
compile project(':spark-common')
- compile 'net.kyori:text-adapter-bungeecord:1.0.3'
+ compile('net.kyori:text-adapter-bungeecord:1.0.3') {
+ exclude(module: 'text')
+ }
compileOnly 'net.md-5:bungeecord-api:1.12-SNAPSHOT'
}
diff --git a/spark-bungeecord/src/main/java/me/lucko/spark/bungeecord/BungeeCordCommandSender.java b/spark-bungeecord/src/main/java/me/lucko/spark/bungeecord/BungeeCordCommandSender.java
new file mode 100644
index 0000000..d3a831c
--- /dev/null
+++ b/spark-bungeecord/src/main/java/me/lucko/spark/bungeecord/BungeeCordCommandSender.java
@@ -0,0 +1,61 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.bungeecord;
+
+import me.lucko.spark.common.CommandSender;
+import net.kyori.text.Component;
+import net.kyori.text.adapter.bungeecord.TextAdapter;
+
+public class BungeeCordCommandSender implements CommandSender {
+ private final net.md_5.bungee.api.CommandSender sender;
+
+ public BungeeCordCommandSender(net.md_5.bungee.api.CommandSender sender) {
+ this.sender = sender;
+ }
+
+ @Override
+ public String getName() {
+ return this.sender.getName();
+ }
+
+ @Override
+ public void sendMessage(Component message) {
+ TextAdapter.sendComponent(this.sender, message);
+ }
+
+ @Override
+ public boolean hasPermission(String permission) {
+ return this.sender.hasPermission(permission);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ BungeeCordCommandSender that = (BungeeCordCommandSender) o;
+ return this.sender.equals(that.sender);
+ }
+
+ @Override
+ public int hashCode() {
+ return this.sender.hashCode();
+ }
+}
diff --git a/spark-bungeecord/src/main/java/me/lucko/spark/bungeecord/SparkBungeeCordPlugin.java b/spark-bungeecord/src/main/java/me/lucko/spark/bungeecord/SparkBungeeCordPlugin.java
index ba2ee99..193ae06 100644
--- a/spark-bungeecord/src/main/java/me/lucko/spark/bungeecord/SparkBungeeCordPlugin.java
+++ b/spark-bungeecord/src/main/java/me/lucko/spark/bungeecord/SparkBungeeCordPlugin.java
@@ -20,27 +20,24 @@
package me.lucko.spark.bungeecord;
+import me.lucko.spark.common.CommandSender;
import me.lucko.spark.common.SparkPlatform;
import me.lucko.spark.common.SparkPlugin;
import me.lucko.spark.common.sampler.ThreadDumper;
import me.lucko.spark.common.sampler.TickCounter;
-import net.kyori.text.Component;
-import net.kyori.text.adapter.bungeecord.TextAdapter;
-import net.md_5.bungee.api.ChatColor;
-import net.md_5.bungee.api.CommandSender;
-import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.TabExecutor;
import java.nio.file.Path;
-import java.util.Collections;
-import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
-public class SparkBungeeCordPlugin extends Plugin implements SparkPlugin<CommandSender> {
+public class SparkBungeeCordPlugin extends Plugin implements SparkPlugin {
- private final SparkPlatform<CommandSender> platform = new SparkPlatform<>(this);
+ private final SparkPlatform platform = new SparkPlatform(this);
@Override
public void onEnable() {
@@ -70,15 +67,10 @@ public class SparkBungeeCordPlugin extends Plugin implements SparkPlugin<Command
@Override
public Set<CommandSender> getSendersWithPermission(String permission) {
- Set<CommandSender> senders = new HashSet<>(getProxy().getPlayers());
+ List<net.md_5.bungee.api.CommandSender> senders = new LinkedList<>(getProxy().getPlayers());
senders.removeIf(sender -> !sender.hasPermission(permission));
senders.add(getProxy().getConsole());
- return senders;
- }
-
- @Override
- public void sendMessage(CommandSender sender, Component message) {
- TextAdapter.sendComponent(sender, message);
+ return senders.stream().map(BungeeCordCommandSender::new).collect(Collectors.toSet());
}
@Override
@@ -105,23 +97,13 @@ public class SparkBungeeCordPlugin extends Plugin implements SparkPlugin<Command
}
@Override
- public void execute(CommandSender sender, String[] args) {
- if (!sender.hasPermission("spark")) {
- TextComponent msg = new TextComponent("You do not have permission to use this command.");
- msg.setColor(ChatColor.RED);
- sender.sendMessage(msg);
- return;
- }
-
- this.plugin.platform.executeCommand(sender, args);
+ public void execute(net.md_5.bungee.api.CommandSender sender, String[] args) {
+ this.plugin.platform.executeCommand(new BungeeCordCommandSender(sender), args);
}
@Override
- public Iterable<String> onTabComplete(CommandSender sender, String[] args) {
- if (!sender.hasPermission("spark")) {
- return Collections.emptyList();
- }
- return this.plugin.platform.tabCompleteCommand(sender, args);
+ public Iterable<String> onTabComplete(net.md_5.bungee.api.CommandSender sender, String[] args) {
+ return this.plugin.platform.tabCompleteCommand(new BungeeCordCommandSender(sender), args);
}
}
}
diff --git a/spark-common/build.gradle b/spark-common/build.gradle
index a8b95c6..8a9ee16 100644
--- a/spark-common/build.gradle
+++ b/spark-common/build.gradle
@@ -1,7 +1,16 @@
dependencies {
compile 'com.squareup.okhttp3:okhttp:3.14.1'
compile 'com.squareup.okio:okio:1.17.3'
- compile 'net.kyori:text-api:2.0.0'
+ compile('net.kyori:text-api:2.0.0') {
+ exclude(module: 'checker-qual')
+ }
+ compile('net.kyori:text-serializer-gson:2.0.0') {
+ exclude(module: 'text-api')
+ exclude(module: 'gson')
+ }
+ compile('net.kyori:text-serializer-legacy:2.0.0') {
+ exclude(module: 'text-api')
+ }
compileOnly 'com.google.code.gson:gson:2.7'
compileOnly 'com.google.guava:guava:19.0'
}
diff --git a/spark-common/src/main/java/me/lucko/spark/common/ActivityLog.java b/spark-common/src/main/java/me/lucko/spark/common/ActivityLog.java
new file mode 100644
index 0000000..4b5e942
--- /dev/null
+++ b/spark-common/src/main/java/me/lucko/spark/common/ActivityLog.java
@@ -0,0 +1,195 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.common;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonPrimitive;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+public class ActivityLog {
+
+ private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
+ private static final JsonParser PARSER = new JsonParser();
+
+ private final Path file;
+
+ private final List<Activity> log = new LinkedList<>();
+ private final Object[] mutex = new Object[0];
+
+ public ActivityLog(Path file) {
+ this.file = file;
+ }
+
+ public void addToLog(Activity activity) {
+ synchronized (this.mutex) {
+ this.log.add(activity);
+ }
+ save();
+ }
+
+ public List<Activity> getLog() {
+ synchronized (this.mutex) {
+ return new LinkedList<>(this.log);
+ }
+ }
+
+ public void save() {
+ JsonArray array = new JsonArray();
+ synchronized (this.mutex) {
+ for (Activity activity : this.log) {
+ if (!activity.shouldExpire()) {
+ array.add(activity.serialize());
+ }
+ }
+ }
+
+ try {
+ Files.createDirectories(this.file.getParent());
+ } catch (IOException e) {
+ // ignore
+ }
+
+ try (BufferedWriter writer = Files.newBufferedWriter(this.file, StandardCharsets.UTF_8)) {
+ GSON.toJson(array, writer);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void load() {
+ if (!Files.exists(this.file)) {
+ synchronized (this.mutex) {
+ this.log.clear();
+ return;
+ }
+ }
+
+ JsonArray array;
+ try (BufferedReader reader = Files.newBufferedReader(this.file, StandardCharsets.UTF_8)) {
+ array = PARSER.parse(reader).getAsJsonArray();
+ } catch (IOException e) {
+ e.printStackTrace();
+ return;
+ }
+
+ boolean save = false;
+
+ synchronized (this.mutex) {
+ this.log.clear();
+ for (JsonElement element : array) {
+ try {
+ Activity activity = Activity.deserialize(element);
+ if (activity.shouldExpire()) {
+ save = true;
+ }
+ this.log.add(activity);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ if (save) {
+ try {
+ save();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+
+ public static final class Activity {
+ private final String user;
+ private final long time;
+ private final String type;
+ private final String url;
+
+ public Activity(String user, long time, String type, String url) {
+ this.user = user;
+ this.time = time;
+ this.type = type;
+ this.url = url;
+ }
+
+ public String getUser() {
+ return this.user;
+ }
+
+ public long getTime() {
+ return this.time;
+ }
+
+ public String getType() {
+ return this.type;
+ }
+
+ public String getUrl() {
+ return this.url;
+ }
+
+ public boolean shouldExpire() {
+ return (System.currentTimeMillis() - this.time) > TimeUnit.DAYS.toMillis(7);
+ }
+
+ public JsonObject serialize() {
+ JsonObject object = new JsonObject();
+
+ JsonObject user = new JsonObject();
+ user.add("name", new JsonPrimitive(this.user));
+ object.add("user", user);
+
+ object.add("time", new JsonPrimitive(this.time));
+ object.add("type", new JsonPrimitive(this.type));
+
+ JsonObject data = new JsonObject();
+ data.add("url", new JsonPrimitive(this.url));
+ object.add("data", data);
+
+ return object;
+ }
+
+ public static Activity deserialize(JsonElement element) {
+ JsonObject object = element.getAsJsonObject();
+
+ String user = object.get("user").getAsJsonObject().get("name").getAsJsonPrimitive().getAsString();
+ long time = object.get("time").getAsJsonPrimitive().getAsLong();
+ String type = object.get("type").getAsJsonPrimitive().getAsString();
+ String url = object.get("data").getAsJsonObject().get("url").getAsJsonPrimitive().getAsString();
+
+ return new Activity(user, time, type, url);
+ }
+ }
+
+}
diff --git a/spark-common/src/main/java/me/lucko/spark/common/CommandSender.java b/spark-common/src/main/java/me/lucko/spark/common/CommandSender.java
new file mode 100644
index 0000000..9d2ecc0
--- /dev/null
+++ b/spark-common/src/main/java/me/lucko/spark/common/CommandSender.java
@@ -0,0 +1,33 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.common;
+
+import net.kyori.text.Component;
+
+public interface CommandSender {
+
+ String getName();
+
+ void sendMessage(Component message);
+
+ boolean hasPermission(String permission);
+
+}
diff --git a/spark-common/src/main/java/me/lucko/spark/common/SparkPlatform.java b/spark-common/src/main/java/me/lucko/spark/common/SparkPlatform.java
index 6b3eb21..d05d9e8 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/SparkPlatform.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/SparkPlatform.java
@@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableList;
import me.lucko.spark.common.command.Arguments;
import me.lucko.spark.common.command.Command;
import me.lucko.spark.common.command.CommandResponseHandler;
+import me.lucko.spark.common.command.modules.ActivityLogModule;
import me.lucko.spark.common.command.modules.HealthModule;
import me.lucko.spark.common.command.modules.MemoryModule;
import me.lucko.spark.common.command.modules.SamplerModule;
@@ -35,6 +36,7 @@ import me.lucko.spark.common.sampler.TickCounter;
import me.lucko.spark.common.util.BytebinClient;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
+import net.kyori.text.event.ClickEvent;
import net.kyori.text.format.TextColor;
import net.kyori.text.format.TextDecoration;
import okhttp3.OkHttpClient;
@@ -47,10 +49,8 @@ import java.util.stream.Collectors;
/**
* Abstract spark implementation used by all platforms.
- *
- * @param <S> the sender (e.g. CommandSender) type used by the platform
*/
-public class SparkPlatform<S> {
+public class SparkPlatform {
/** The URL of the viewer frontend */
public static final String VIEWER_URL = "https://sparkprofiler.github.io/#";
@@ -59,22 +59,26 @@ public class SparkPlatform<S> {
/** The bytebin instance used by the platform */
public static final BytebinClient BYTEBIN_CLIENT = new BytebinClient(OK_HTTP_CLIENT, "https://bytebin.lucko.me/", "spark-plugin");
- private final List<Command<S>> commands;
- private final SparkPlugin<S> plugin;
-
+ private final SparkPlugin plugin;
+ private final List<Command> commands;
+ private final ActivityLog activityLog;
private final TickCounter tickCounter;
private final TpsCalculator tpsCalculator;
- public SparkPlatform(SparkPlugin<S> plugin) {
+ public SparkPlatform(SparkPlugin plugin) {
this.plugin = plugin;
- ImmutableList.Builder<Command<S>> commandsBuilder = ImmutableList.builder();
- new SamplerModule<S>().registerCommands(commandsBuilder::add);
- new HealthModule<S>().registerCommands(commandsBuilder::add);
- new TickMonitoringModule<S>().registerCommands(commandsBuilder::add);
- new MemoryModule<S>().registerCommands(commandsBuilder::add);
+ ImmutableList.Builder<Command> commandsBuilder = ImmutableList.builder();
+ new SamplerModule().registerCommands(commandsBuilder::add);
+ new HealthModule().registerCommands(commandsBuilder::add);
+ new TickMonitoringModule().registerCommands(commandsBuilder::add);
+ new MemoryModule().registerCommands(commandsBuilder::add);
+ new ActivityLogModule().registerCommands(commandsBuilder::add);
this.commands = commandsBuilder.build();
+ this.activityLog = new ActivityLog(plugin.getPluginFolder().resolve("activity.json"));
+ this.activityLog.load();
+
this.tickCounter = plugin.createTickCounter();
this.tpsCalculator = this.tickCounter != null ? new TpsCalculator() : null;
}
@@ -92,10 +96,14 @@ public class SparkPlatform<S> {
}
}
- public SparkPlugin<S> getPlugin() {
+ public SparkPlugin getPlugin() {
return this.plugin;
}
+ public ActivityLog getActivityLog() {
+ return this.activityLog;
+ }
+
public TickCounter getTickCounter() {
return this.tickCounter;
}
@@ -104,17 +112,39 @@ public class SparkPlatform<S> {
return this.tpsCalculator;
}
- public void executeCommand(S sender, String[] args) {
- CommandResponseHandler<S> resp = new CommandResponseHandler<>(this, sender);
+ public void executeCommand(CommandSender sender, String[] args) {
+ CommandResponseHandler resp = new CommandResponseHandler(this, sender);
+
+ if (!sender.hasPermission("spark")) {
+ resp.replyPrefixed(TextComponent.of("You do not have permission to use this command.", TextColor.RED));
+ return;
+ }
+
if (args.length == 0) {
- sendUsage(resp);
+ resp.replyPrefixed(TextComponent.builder("")
+ .append(TextComponent.of("spark", TextColor.WHITE))
+ .append(Component.space())
+ .append(TextComponent.of("v" + getPlugin().getVersion(), TextColor.GRAY))
+ .build()
+ );
+ resp.replyPrefixed(TextComponent.builder("").color(TextColor.GRAY)
+ .append(TextComponent.of("Use "))
+ .append(TextComponent.builder("/" + getPlugin().getLabel() + " help")
+ .color(TextColor.WHITE)
+ .decoration(TextDecoration.UNDERLINED, true)
+ .clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, getPlugin().getLabel() + " help"))
+ .build()
+ )
+ .append(TextComponent.of(" to view usage information."))
+ .build()
+ );
return;
}
ArrayList<String> rawArgs = new ArrayList<>(Arrays.asList(args));
String alias = rawArgs.remove(0).toLowerCase();
- for (Command<S> command : this.commands) {
+ for (Command command : this.commands) {
if (command.aliases().contains(alias)) {
try {
command.executor().execute(this, sender, resp, new Arguments(rawArgs));
@@ -129,7 +159,11 @@ public class SparkPlatform<S> {
sendUsage(resp);
}
- public List<String> tabCompleteCommand(S sender, String[] args) {
+ public List<String> tabCompleteCommand(CommandSender sender, String[] args) {
+ if (!sender.hasPermission("spark")) {
+ return Collections.emptyList();
+ }
+
List<String> arguments = new ArrayList<>(Arrays.asList(args));
if (args.length <= 1) {
@@ -140,7 +174,7 @@ public class SparkPlatform<S> {
}
String alias = arguments.remove(0);
- for (Command<S> command : this.commands) {
+ for (Command command : this.commands) {
if (command.aliases().contains(alias)) {
return command.tabCompleter().completions(this, sender, arguments);
}
@@ -149,18 +183,20 @@ public class SparkPlatform<S> {
return Collections.emptyList();
}
- private void sendUsage(CommandResponseHandler<S> sender) {
- sender.replyPrefixed(TextComponent.builder()
+ private void sendUsage(CommandResponseHandler sender) {
+ sender.replyPrefixed(TextComponent.builder("")
.append(TextComponent.of("spark", TextColor.WHITE))
.append(Component.space())
.append(TextComponent.of("v" + getPlugin().getVersion(), TextColor.GRAY))
.build()
);
- for (Command<S> command : this.commands) {
- sender.reply(TextComponent.builder()
+ for (Command command : this.commands) {
+ String usage = getPlugin().getLabel() + " " + command.aliases().get(0);
+ ClickEvent clickEvent = new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, usage);
+ sender.reply(TextComponent.builder("")
.append(TextComponent.builder(">").color(TextColor.GOLD).decoration(TextDecoration.BOLD, true).build())
.append(Component.space())
- .append(TextComponent.of("/" + getPlugin().getLabel() + " " + command.aliases().get(0), TextColor.GRAY))
+ .append(TextComponent.builder("/" + usage).color(TextColor.GRAY).clickEvent(clickEvent).build())
.build()
);
for (Command.ArgumentInfo arg : command.arguments()) {
diff --git a/spark-common/src/main/java/me/lucko/spark/common/SparkPlugin.java b/spark-common/src/main/java/me/lucko/spark/common/SparkPlugin.java
index 19eb3d3..175fda5 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/SparkPlugin.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/SparkPlugin.java
@@ -22,12 +22,11 @@ package me.lucko.spark.common;
import me.lucko.spark.common.sampler.ThreadDumper;
import me.lucko.spark.common.sampler.TickCounter;
-import net.kyori.text.Component;
import java.nio.file.Path;
import java.util.Set;
-public interface SparkPlugin<S> {
+public interface SparkPlugin {
String getVersion();
@@ -35,9 +34,7 @@ public interface SparkPlugin<S> {
String getLabel();
- Set<S> getSendersWithPermission(String permission);
-
- void sendMessage(S sender, Component message);
+ Set<CommandSender> getSendersWithPermission(String permission);
void runAsync(Runnable r);
diff --git a/spark-common/src/main/java/me/lucko/spark/common/command/Command.java b/spark-common/src/main/java/me/lucko/spark/common/command/Command.java
index c9f6551..ab95cb6 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/command/Command.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/command/Command.java
@@ -21,24 +21,25 @@
package me.lucko.spark.common.command;
import com.google.common.collect.ImmutableList;
+import me.lucko.spark.common.CommandSender;
import me.lucko.spark.common.SparkPlatform;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
-public class Command<S> {
+public class Command {
- public static <S> Builder<S> builder() {
- return new Builder<>();
+ public static Builder builder() {
+ return new Builder();
}
private final List<String> aliases;
private final List<ArgumentInfo> arguments;
- private final Executor<S> executor;
- private final TabCompleter<S> tabCompleter;
+ private final Executor executor;
+ private final TabCompleter tabCompleter;
- private Command(List<String> aliases, List<ArgumentInfo> arguments, Executor<S> executor, TabCompleter<S> tabCompleter) {
+ private Command(List<String> aliases, List<ArgumentInfo> arguments, Executor executor, TabCompleter tabCompleter) {
this.aliases = aliases;
this.arguments = arguments;
this.executor = executor;
@@ -53,45 +54,45 @@ public class Command<S> {
return this.arguments;
}
- public Executor<S> executor() {
+ public Executor executor() {
return this.executor;
}
- public TabCompleter<S> tabCompleter() {
+ public TabCompleter tabCompleter() {
return this.tabCompleter;
}
- public static final class Builder<S> {
+ public static final class Builder {
private final ImmutableList.Builder<String> aliases = ImmutableList.builder();
private final ImmutableList.Builder<ArgumentInfo> arguments = ImmutableList.builder();
- private Executor<S> executor = null;
- private TabCompleter<S> tabCompleter = null;
+ private Executor executor = null;
+ private TabCompleter tabCompleter = null;
Builder() {
}
- public Builder<S> aliases(String... aliases) {
+ public Builder aliases(String... aliases) {
this.aliases.add(aliases);
return this;
}
- public Builder<S> argumentUsage(String argumentName, String parameterDescription) {
+ public Builder argumentUsage(String argumentName, String parameterDescription) {
this.arguments.add(new ArgumentInfo(argumentName, parameterDescription));
return this;
}
- public Builder<S> executor(Executor<S> executor) {
+ public Builder executor(Executor executor) {
this.executor = Objects.requireNonNull(executor, "executor");
return this;
}
- public Builder<S> tabCompleter(TabCompleter<S> tabCompleter) {
+ public Builder tabCompleter(TabCompleter tabCompleter) {
this.tabCompleter = Objects.requireNonNull(tabCompleter, "tabCompleter");
return this;
}
- public Command<S> build() {
+ public Command build() {
List<String> aliases = this.aliases.build();
if (aliases.isEmpty()) {
throw new IllegalStateException("No aliases defined");
@@ -102,22 +103,22 @@ public class Command<S> {
if (this.tabCompleter == null) {
this.tabCompleter = TabCompleter.empty();
}
- return new Command<>(aliases, this.arguments.build(), this.executor, this.tabCompleter);
+ return new Command(aliases, this.arguments.build(), this.executor, this.tabCompleter);
}
}
@FunctionalInterface
- public interface Executor<S> {
- void execute(SparkPlatform<S> platform, S sender, CommandResponseHandler resp, Arguments arguments);
+ public interface Executor {
+ void execute(SparkPlatform platform, CommandSender sender, CommandResponseHandler resp, Arguments arguments);
}
@FunctionalInterface
- public interface TabCompleter<S> {
- static <S> TabCompleter<S> empty() {
+ public interface TabCompleter {
+ static <S> TabCompleter empty() {
return (platform, sender, arguments) -> Collections.emptyList();
}
- List<String> completions(SparkPlatform<S> platform, S sender, List<String> arguments);
+ List<String> completions(SparkPlatform platform, CommandSender sender, List<String> arguments);
}
public static final class ArgumentInfo {
diff --git a/spark-common/src/main/java/me/lucko/spark/common/command/CommandModule.java b/spark-common/src/main/java/me/lucko/spark/common/command/CommandModule.java
index f195ef2..76c24b3 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/command/CommandModule.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/command/CommandModule.java
@@ -22,8 +22,8 @@ package me.lucko.spark.common.command;
import java.util.function.Consumer;
-public interface CommandModule<S> {
+public interface CommandModule {
- void registerCommands(Consumer<Command<S>> consumer);
+ void registerCommands(Consumer<Command> consumer);
}
diff --git a/spark-common/src/main/java/me/lucko/spark/common/command/CommandResponseHandler.java b/spark-common/src/main/java/me/lucko/spark/common/command/CommandResponseHandler.java
index 94e1946..d31d1cf 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/command/CommandResponseHandler.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/command/CommandResponseHandler.java
@@ -20,50 +20,50 @@
package me.lucko.spark.common.command;
+import me.lucko.spark.common.CommandSender;
import me.lucko.spark.common.SparkPlatform;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
-import net.kyori.text.event.ClickEvent;
import net.kyori.text.format.TextColor;
import net.kyori.text.format.TextDecoration;
import java.util.Set;
import java.util.function.Consumer;
-public class CommandResponseHandler<S> {
+public class CommandResponseHandler {
/** The prefix used in all messages "&8[&e&lâš¡&8] &7" */
- private static final TextComponent PREFIX = TextComponent.builder().color(TextColor.GRAY)
+ private static final TextComponent PREFIX = TextComponent.builder("").color(TextColor.GRAY)
.append(TextComponent.of("[", TextColor.DARK_GRAY))
.append(TextComponent.builder("âš¡").color(TextColor.YELLOW).decoration(TextDecoration.BOLD, TextDecoration.State.TRUE).build())
.append(TextComponent.of("]", TextColor.DARK_GRAY))
.append(TextComponent.of(" "))
.build();
- private final SparkPlatform<S> platform;
- private final S sender;
+ private final SparkPlatform platform;
+ private final CommandSender sender;
- public CommandResponseHandler(SparkPlatform<S> platform, S sender) {
+ public CommandResponseHandler(SparkPlatform platform, CommandSender sender) {
this.platform = platform;
this.sender = sender;
}
- public S sender() {
+ public CommandSender sender() {
return this.sender;
}
- public void allSenders(Consumer<? super S> action) {
- Set<S> senders = this.platform.getPlugin().getSendersWithPermission("spark");
+ public void allSenders(Consumer<? super CommandSender> action) {
+ Set<CommandSender> senders = this.platform.getPlugin().getSendersWithPermission("spark");
senders.add(this.sender);
senders.forEach(action);
}
public void reply(Component message) {
- this.platform.getPlugin().sendMessage(this.sender, message);
+ this.sender.sendMessage(message);
}
public void broadcast(Component message) {
- allSenders(sender -> this.platform.getPlugin().sendMessage(sender, message));
+ allSenders(sender -> sender.sendMessage(message));
}
public void replyPrefixed(Component message) {
diff --git a/spark-common/src/main/java/me/lucko/spark/common/command/modules/ActivityLogModule.java b/spark-common/src/main/java/me/lucko/spark/common/command/modules/ActivityLogModule.java
new file mode 100644
index 0000000..ad6b3e8
--- /dev/null
+++ b/spark-common/src/main/java/me/lucko/spark/common/command/modules/ActivityLogModule.java
@@ -0,0 +1,120 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.common.command.modules;
+
+import me.lucko.spark.common.ActivityLog;
+import me.lucko.spark.common.command.Command;
+import me.lucko.spark.common.command.CommandModule;
+import net.kyori.text.Component;
+import net.kyori.text.TextComponent;
+import net.kyori.text.event.ClickEvent;
+import net.kyori.text.format.TextColor;
+import net.kyori.text.format.TextDecoration;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+public class ActivityLogModule implements CommandModule {
+
+ @Override
+ public void registerCommands(Consumer<Command> consumer) {
+ consumer.accept(Command.builder()
+ .aliases("activity", "activitylog", "log")
+ .executor((platform, sender, resp, arguments) -> {
+ List<ActivityLog.Activity> log = platform.getActivityLog().getLog();
+ log.removeIf(ActivityLog.Activity::shouldExpire);
+
+ if (log.isEmpty()) {
+ resp.replyPrefixed(TextComponent.of("There are no entries present in the log."));
+ return;
+ }
+
+ resp.replyPrefixed(TextComponent.of("Showing recent spark activity...", TextColor.GOLD));
+
+ int count = 0;
+ for (ActivityLog.Activity activity : log) {
+ count++;
+
+ resp.replyPrefixed(TextComponent.builder("")
+ .append(TextComponent.builder(">").color(TextColor.DARK_GRAY).decoration(TextDecoration.BOLD, true).build())
+ .append(Component.space())
+ .append(TextComponent.of("#" + count, TextColor.WHITE))
+ .append(TextComponent.of(" - ", TextColor.DARK_GRAY))
+ .append(TextComponent.of(activity.getType(), TextColor.YELLOW))
+ .append(TextComponent.of(" - ", TextColor.DARK_GRAY))
+ .append(TextComponent.of(formatDateDiff(activity.getTime()), TextColor.GRAY))
+ .build()
+ );
+ resp.replyPrefixed(TextComponent.builder(" ")
+ .append(TextComponent.of("Created by: ", TextColor.GRAY))
+ .append(TextComponent.of(activity.getUser(), TextColor.WHITE))
+ .build()
+ );
+ resp.replyPrefixed(TextComponent.builder(" ")
+ .append(TextComponent.of("Link: ", TextColor.GRAY))
+ .append(TextComponent.builder(activity.getUrl())
+ .color(TextColor.WHITE)
+ .decoration(TextDecoration.UNDERLINED, true)
+ .clickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, activity.getUrl()))
+ .build()
+ )
+ .build()
+ );
+ resp.reply(Component.space());
+ }
+ })
+ .tabCompleter(Command.TabCompleter.empty())
+ .build()
+ );
+ }
+
+ private static String formatDateDiff(long time) {
+ long seconds = (System.currentTimeMillis() - time) / 1000;
+
+ if (seconds <= 0) {
+ return "now";
+ }
+
+ long minute = seconds / 60;
+ seconds = seconds % 60;
+ long hour = minute / 60;
+ minute = minute % 60;
+ long day = hour / 24;
+ hour = hour % 24;
+
+ StringBuilder sb = new StringBuilder();
+ if (day != 0) {
+ sb.append(day).append("d ");
+ }
+ if (hour != 0) {
+ sb.append(hour).append("h ");
+ }
+ if (minute != 0) {
+ sb.append(minute).append("m ");
+ }
+ if (seconds != 0) {
+ sb.append(seconds).append("s");
+ }
+
+ return sb.toString().trim() + " ago";
+ }
+
+}
diff --git a/spark-common/src/main/java/me/lucko/spark/common/command/modules/HealthModule.java b/spark-common/src/main/java/me/lucko/spark/common/command/modules/HealthModule.java
index 097d264..83f9006 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/command/modules/HealthModule.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/command/modules/HealthModule.java
@@ -44,11 +44,11 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
-public class HealthModule<S> implements CommandModule<S> {
+public class HealthModule implements CommandModule {
@Override
- public void registerCommands(Consumer<Command<S>> consumer) {
- consumer.accept(Command.<S>builder()
+ public void registerCommands(Consumer<Command> consumer) {
+ consumer.accept(Command.builder()
.aliases("tps")
.executor((platform, sender, resp, arguments) -> {
TpsCalculator tpsCalculator = platform.getTpsCalculator();
@@ -63,7 +63,7 @@ public class HealthModule<S> implements CommandModule<S> {
.build()
);
- consumer.accept(Command.<S>builder()
+ consumer.accept(Command.builder()
.aliases("healthreport", "health", "ht")
.argumentUsage("memory", null)
.executor((platform, sender, resp, arguments) -> {
@@ -74,7 +74,7 @@ public class HealthModule<S> implements CommandModule<S> {
TpsCalculator tpsCalculator = platform.getTpsCalculator();
if (tpsCalculator != null) {
- report.add(TextComponent.builder()
+ report.add(TextComponent.builder("")
.append(TextComponent.builder(">").color(TextColor.DARK_GRAY).decoration(TextDecoration.BOLD, true).build())
.append(Component.space())
.append(TextComponent.of("TPS from last 5s, 10s, 1m, 5m, 15m:", TextColor.GOLD))
@@ -86,7 +86,7 @@ public class HealthModule<S> implements CommandModule<S> {
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
MemoryUsage heapUsage = memoryMXBean.getHeapMemoryUsage();
- report.add(TextComponent.builder()
+ report.add(TextComponent.builder("")
.append(TextComponent.builder(">").color(TextColor.DARK_GRAY).decoration(TextDecoration.BOLD, true).build())
.append(Component.space())
.append(TextComponent.of("Memory usage:", TextColor.GOLD))
@@ -109,7 +109,7 @@ public class HealthModule<S> implements CommandModule<S> {
if (arguments.boolFlag("memory")) {
MemoryUsage nonHeapUsage = memoryMXBean.getNonHeapMemoryUsage();
- report.add(TextComponent.builder()
+ report.add(TextComponent.builder("")
.append(TextComponent.builder(">").color(TextColor.DARK_GRAY).decoration(TextDecoration.BOLD, true).build())
.append(Component.space())
.append(TextComponent.of("Non-heap memory usage:", TextColor.GOLD))
@@ -134,7 +134,7 @@ public class HealthModule<S> implements CommandModule<S> {
usage = new MemoryUsage(usage.getInit(), usage.getUsed(), usage.getCommitted(), usage.getCommitted());
}
- report.add(TextComponent.builder()
+ report.add(TextComponent.builder("")
.append(TextComponent.builder(">").color(TextColor.DARK_GRAY).decoration(TextDecoration.BOLD, true).build())
.append(Component.space())
.append(TextComponent.of(memoryPool.getName() + " pool usage:", TextColor.GOLD))
@@ -172,7 +172,7 @@ public class HealthModule<S> implements CommandModule<S> {
double processCpuLoad = CpuMonitor.getProcessCpuLoad();
if (systemCpuLoad >= 0 || processCpuLoad >= 0) {
- report.add(TextComponent.builder()
+ report.add(TextComponent.builder("")
.append(TextComponent.builder(">").color(TextColor.DARK_GRAY).decoration(TextDecoration.BOLD, true).build())
.append(Component.space())
.append(TextComponent.of("CPU usage:", TextColor.GOLD))
@@ -203,7 +203,7 @@ public class HealthModule<S> implements CommandModule<S> {
FileStore fileStore = Files.getFileStore(Paths.get("."));
long totalSpace = fileStore.getTotalSpace();
long usedSpace = totalSpace - fileStore.getUsableSpace();
- report.add(TextComponent.builder()
+ report.add(TextComponent.builder("")
.append(TextComponent.builder(">").color(TextColor.DARK_GRAY).decoration(TextDecoration.BOLD, true).build())
.append(Component.space())
.append(TextComponent.of("Disk usage:", TextColor.GOLD))
@@ -227,7 +227,7 @@ public class HealthModule<S> implements CommandModule<S> {
e.printStackTrace();
}
- TextComponent.Builder builder = TextComponent.builder();
+ TextComponent.Builder builder = TextComponent.builder("");
report.forEach(line -> builder.append(line).append(Component.newline()));
resp.reply(builder.build());
});
@@ -259,7 +259,7 @@ public class HealthModule<S> implements CommandModule<S> {
line.append(TextComponent.of(Strings.repeat(" ", (length - committedChars))));
}
- return TextComponent.builder()
+ return TextComponent.builder("")
.append(TextComponent.of("[", TextColor.DARK_GRAY))
.append(line.build())
.append(TextComponent.of("]", TextColor.DARK_GRAY))
@@ -293,7 +293,7 @@ public class HealthModule<S> implements CommandModule<S> {
line.append(TextComponent.of(Strings.repeat(" ", (length - committedChars))));
}
- return TextComponent.builder()
+ return TextComponent.builder("")
.append(TextComponent.of("[", TextColor.DARK_GRAY))
.append(line.build())
.append(TextComponent.of("]", TextColor.DARK_GRAY))
@@ -303,7 +303,7 @@ public class HealthModule<S> implements CommandModule<S> {
private static TextComponent generateCpuUsageDiagram(double usage, int length) {
int usedChars = (int) ((usage * length));
String line = Strings.repeat("/", usedChars) + Strings.repeat(" ", length - usedChars);
- return TextComponent.builder()
+ return TextComponent.builder("")
.append(TextComponent.of("[", TextColor.DARK_GRAY))
.append(TextComponent.of(line, TextColor.GRAY))
.append(TextComponent.of("]", TextColor.DARK_GRAY))
@@ -313,7 +313,7 @@ public class HealthModule<S> implements CommandModule<S> {
private static TextComponent generateDiskUsageDiagram(double used, double max, int length) {
int usedChars = (int) ((used * length) / max);
String line = Strings.repeat("/", usedChars) + Strings.repeat(" ", length - usedChars);
- return TextComponent.builder()
+ return TextComponent.builder("")
.append(TextComponent.of("[", TextColor.DARK_GRAY))
.append(TextComponent.of(line, TextColor.GRAY))
.append(TextComponent.of("]", TextColor.DARK_GRAY))
diff --git a/spark-common/src/main/java/me/lucko/spark/common/command/modules/MemoryModule.java b/spark-common/src/main/java/me/lucko/spark/common/command/modules/MemoryModule.java
index e2d817d..b65db78 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/command/modules/MemoryModule.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/command/modules/MemoryModule.java
@@ -20,6 +20,7 @@
package me.lucko.spark.common.command.modules;
+import me.lucko.spark.common.ActivityLog;
import me.lucko.spark.common.SparkPlatform;
import me.lucko.spark.common.command.Command;
import me.lucko.spark.common.command.CommandModule;
@@ -38,12 +39,12 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.function.Consumer;
-public class MemoryModule<S> implements CommandModule<S> {
+public class MemoryModule implements CommandModule {
private static final MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8");
@Override
- public void registerCommands(Consumer<Command<S>> consumer) {
- consumer.accept(Command.<S>builder()
+ public void registerCommands(Consumer<Command> consumer) {
+ consumer.accept(Command.builder()
.aliases("heapsummary")
.argumentUsage("run-gc-before", null)
.executor((platform, sender, resp, arguments) -> {
@@ -75,6 +76,8 @@ public class MemoryModule<S> implements CommandModule<S> {
.clickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url))
.build()
);
+
+ platform.getActivityLog().addToLog(new ActivityLog.Activity(sender.getName(), System.currentTimeMillis(), "Heap dump summary", url));
} catch (IOException e) {
resp.broadcastPrefixed(TextComponent.of("An error occurred whilst uploading the data.", TextColor.RED));
e.printStackTrace();
@@ -85,7 +88,7 @@ public class MemoryModule<S> implements CommandModule<S> {
.build()
);
- consumer.accept(Command.<S>builder()
+ consumer.accept(Command.builder()
.aliases("heapdump")
.argumentUsage("run-gc-before", null)
.argumentUsage("include-non-live", null)
diff --git a/spark-common/src/main/java/me/lucko/spark/common/command/modules/SamplerModule.java b/spark-common/src/main/java/me/lucko/spark/common/command/modules/SamplerModule.java
index e450b0b..fb1bc72 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/command/modules/SamplerModule.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/command/modules/SamplerModule.java
@@ -20,6 +20,7 @@
package me.lucko.spark.common.command.modules;
+import me.lucko.spark.common.ActivityLog;
import me.lucko.spark.common.SparkPlatform;
import me.lucko.spark.common.command.Command;
import me.lucko.spark.common.command.CommandModule;
@@ -46,7 +47,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
-public class SamplerModule<S> implements CommandModule<S> {
+public class SamplerModule implements CommandModule {
private static final MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8");
/** Guards {@link #activeSampler} */
@@ -55,8 +56,8 @@ public class SamplerModule<S> implements CommandModule<S> {
private Sampler activeSampler = null;
@Override
- public void registerCommands(Consumer<Command<S>> consumer) {
- consumer.accept(Command.<S>builder()
+ public void registerCommands(Consumer<Command> consumer) {
+ consumer.accept(Command.builder()
.aliases("sampler")
.argumentUsage("info", null)
.argumentUsage("stop", null)
@@ -246,7 +247,7 @@ public class SamplerModule<S> implements CommandModule<S> {
);
}
- private void handleUpload(SparkPlatform<S> platform, CommandResponseHandler<S> resp, Sampler sampler) {
+ private void handleUpload(SparkPlatform platform, CommandResponseHandler resp, Sampler sampler) {
platform.getPlugin().runAsync(() -> {
byte[] output = sampler.formCompressedDataPayload();
try {
@@ -259,6 +260,8 @@ public class SamplerModule<S> implements CommandModule<S> {
.clickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url))
.build()
);
+
+ platform.getActivityLog().addToLog(new ActivityLog.Activity(resp.sender().getName(), System.currentTimeMillis(), "Sampler", url));
} catch (IOException e) {
resp.broadcastPrefixed(TextComponent.of("An error occurred whilst uploading the results.", TextColor.RED));
e.printStackTrace();
diff --git a/spark-common/src/main/java/me/lucko/spark/common/command/modules/TickMonitoringModule.java b/spark-common/src/main/java/me/lucko/spark/common/command/modules/TickMonitoringModule.java
index 3b26018..cbcf557 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/command/modules/TickMonitoringModule.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/command/modules/TickMonitoringModule.java
@@ -32,14 +32,14 @@ import net.kyori.text.format.TextColor;
import java.util.function.Consumer;
-public class TickMonitoringModule<S> implements CommandModule<S> {
+public class TickMonitoringModule implements CommandModule {
/** The tick monitor instance currently running, if any */
private ReportingTickMonitor activeTickMonitor = null;
@Override
- public void registerCommands(Consumer<Command<S>> consumer) {
- consumer.accept(Command.<S>builder()
+ public void registerCommands(Consumer<Command> consumer) {
+ consumer.accept(Command.builder()
.aliases("tickmonitoring")
.argumentUsage("threshold", "percentage increase")
.argumentUsage("without-gc", null)
@@ -71,9 +71,9 @@ public class TickMonitoringModule<S> implements CommandModule<S> {
}
private class ReportingTickMonitor extends TickMonitor {
- private final CommandResponseHandler<S> resp;
+ private final CommandResponseHandler resp;
- ReportingTickMonitor(CommandResponseHandler<S> resp, TickCounter tickCounter, int percentageChangeThreshold, boolean monitorGc) {
+ ReportingTickMonitor(CommandResponseHandler resp, TickCounter tickCounter, int percentageChangeThreshold, boolean monitorGc) {
super(tickCounter, percentageChangeThreshold, monitorGc);
this.resp = resp;
}
diff --git a/spark-common/src/main/java/me/lucko/spark/common/monitor/tick/TickMonitor.java b/spark-common/src/main/java/me/lucko/spark/common/monitor/tick/TickMonitor.java
index 3d91368..5e1ec54 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/monitor/tick/TickMonitor.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/monitor/tick/TickMonitor.java
@@ -21,14 +21,12 @@
package me.lucko.spark.common.monitor.tick;
import com.sun.management.GarbageCollectionNotificationInfo;
-import com.sun.org.apache.regexp.internal.RE;
import me.lucko.spark.common.monitor.memory.GarbageCollectionMonitor;
import me.lucko.spark.common.sampler.TickCounter;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.format.TextColor;
-import java.awt.*;
import java.text.DecimalFormat;
import java.util.DoubleSummaryStatistics;
@@ -96,7 +94,7 @@ public abstract class TickMonitor implements TickCounter.TickTask, GarbageCollec
// move onto the next state
if (this.averageTickTime.getCount() >= 120) {
sendMessage(TextComponent.of("Analysis is now complete.", TextColor.GOLD));
- sendMessage(TextComponent.builder().color(TextColor.GRAY)
+ sendMessage(TextComponent.builder("").color(TextColor.GRAY)
.append(TextComponent.of(">", TextColor.WHITE))
.append(Component.space())
.append(TextComponent.of("Max: "))
@@ -104,7 +102,7 @@ public abstract class TickMonitor implements TickCounter.TickTask, GarbageCollec
.append(TextComponent.of("ms"))
.build()
);
- sendMessage(TextComponent.builder().color(TextColor.GRAY)
+ sendMessage(TextComponent.builder("").color(TextColor.GRAY)
.append(TextComponent.of(">", TextColor.WHITE))
.append(Component.space())
.append(TextComponent.of("Min: "))
@@ -112,7 +110,7 @@ public abstract class TickMonitor implements TickCounter.TickTask, GarbageCollec
.append(TextComponent.of("ms"))
.build()
);
- sendMessage(TextComponent.builder().color(TextColor.GRAY)
+ sendMessage(TextComponent.builder("").color(TextColor.GRAY)
.append(TextComponent.of(">", TextColor.WHITE))
.append(Component.space())
.append(TextComponent.of("Avg: "))
@@ -136,7 +134,7 @@ public abstract class TickMonitor implements TickCounter.TickTask, GarbageCollec
double percentageChange = (increase * 100d) / this.avg;
if (percentageChange > this.percentageChangeThreshold) {
- sendMessage(TextComponent.builder().color(TextColor.GRAY)
+ sendMessage(TextComponent.builder("").color(TextColor.GRAY)
.append(TextComponent.of("Tick "))
.append(TextComponent.of("#" + counter.getCurrentTick(), TextColor.DARK_GRAY))
.append(TextComponent.of(" lasted "))
@@ -166,7 +164,7 @@ public abstract class TickMonitor implements TickCounter.TickTask, GarbageCollec
gcType = "Old Gen GC";
}
- sendMessage(TextComponent.builder().color(TextColor.GRAY)
+ sendMessage(TextComponent.builder("").color(TextColor.GRAY)
.append(TextComponent.of("Tick "))
.append(TextComponent.of("#" + this.tickCounter.getCurrentTick(), TextColor.DARK_GRAY))
.append(TextComponent.of(" included "))
diff --git a/spark-common/src/main/java/me/lucko/spark/common/monitor/tick/TpsCalculator.java b/spark-common/src/main/java/me/lucko/spark/common/monitor/tick/TpsCalculator.java
index 90a7b78..2278e0c 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/monitor/tick/TpsCalculator.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/monitor/tick/TpsCalculator.java
@@ -103,7 +103,7 @@ public class TpsCalculator implements TickCounter.TickTask {
}
public TextComponent toFormattedComponent() {
- return TextComponent.builder()
+ return TextComponent.builder("")
.append(format(this.tps5S.getAverage())).append(TextComponent.of(", "))
.append(format(this.tps10S.getAverage())).append(TextComponent.of(", "))
.append(format(this.tps1M.getAverage())).append(TextComponent.of(", "))
diff --git a/spark-forge/build.gradle b/spark-forge/build.gradle
index a8c31cb..140612d 100644
--- a/spark-forge/build.gradle
+++ b/spark-forge/build.gradle
@@ -34,12 +34,6 @@ processResources {
dependencies {
compile project(':spark-common')
-
- compile 'net.kyori:text:1.11-1.6.4', {
- exclude(module: 'checker-qual')
- exclude(module: 'guava')
- exclude(module: 'gson')
- }
}
shadowJar {
diff --git a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeClientSparkPlugin.java b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeClientSparkPlugin.java
index b214308..ec6a0fc 100644
--- a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeClientSparkPlugin.java
+++ b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeClientSparkPlugin.java
@@ -20,10 +20,10 @@
package me.lucko.spark.forge;
+import me.lucko.spark.common.CommandSender;
import me.lucko.spark.common.sampler.TickCounter;
import net.minecraft.client.Minecraft;
import net.minecraft.command.ICommandSender;
-import net.minecraft.server.MinecraftServer;
import net.minecraftforge.client.ClientCommandHandler;
import net.minecraftforge.fml.common.gameevent.TickEvent;
@@ -43,8 +43,13 @@ public class ForgeClientSparkPlugin extends ForgeSparkPlugin {
}
@Override
- public Set<ICommandSender> getSendersWithPermission(String permission) {
- return new HashSet<>(Collections.singleton(Minecraft.getMinecraft().player));
+ boolean hasPermission(ICommandSender sender, String permission) {
+ return true;
+ }
+
+ @Override
+ public Set<CommandSender> getSendersWithPermission(String permission) {
+ return new HashSet<>(Collections.singleton(new ForgeCommandSender(Minecraft.getMinecraft().player, this)));
}
@Override
@@ -66,9 +71,4 @@ public class ForgeClientSparkPlugin extends ForgeSparkPlugin {
public List<String> getAliases() {
return Collections.singletonList("sparkclient");
}
-
- @Override
- public boolean checkPermission(MinecraftServer server, ICommandSender sender) {
- return true;
- }
}
diff --git a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeCommandSender.java b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeCommandSender.java
new file mode 100644
index 0000000..4b71d86
--- /dev/null
+++ b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeCommandSender.java
@@ -0,0 +1,66 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.forge;
+
+import me.lucko.spark.common.CommandSender;
+import net.kyori.text.Component;
+import net.kyori.text.serializer.gson.GsonComponentSerializer;
+import net.minecraft.command.ICommandSender;
+import net.minecraft.util.text.ITextComponent;
+
+public class ForgeCommandSender implements CommandSender {
+ private final ICommandSender sender;
+ private final ForgeSparkPlugin plugin;
+
+ public ForgeCommandSender(ICommandSender sender, ForgeSparkPlugin plugin) {
+ this.sender = sender;
+ this.plugin = plugin;
+ }
+
+ @Override
+ public String getName() {
+ return this.sender.getName();
+ }
+
+ @Override
+ public void sendMessage(Component message) {
+ ITextComponent component = ITextComponent.Serializer.jsonToComponent(GsonComponentSerializer.INSTANCE.serialize(message));
+ this.sender.sendMessage(component);
+ }
+
+ @Override
+ public boolean hasPermission(String permission) {
+ return this.plugin.hasPermission(this.sender, permission);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ForgeCommandSender that = (ForgeCommandSender) o;
+ return this.sender.equals(that.sender);
+ }
+
+ @Override
+ public int hashCode() {
+ return this.sender.hashCode();
+ }
+}
diff --git a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeServerSparkPlugin.java b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeServerSparkPlugin.java
index 167aa94..ba56f44 100644
--- a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeServerSparkPlugin.java
+++ b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeServerSparkPlugin.java
@@ -20,6 +20,7 @@
package me.lucko.spark.forge;
+import me.lucko.spark.common.CommandSender;
import me.lucko.spark.common.sampler.TickCounter;
import net.minecraft.command.ICommandSender;
import net.minecraft.server.MinecraftServer;
@@ -27,9 +28,10 @@ import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import java.util.Collections;
-import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
public class ForgeServerSparkPlugin extends ForgeSparkPlugin {
public ForgeServerSparkPlugin(SparkForgeMod mod) {
@@ -37,12 +39,17 @@ public class ForgeServerSparkPlugin extends ForgeSparkPlugin {
}
@Override
- public Set<ICommandSender> getSendersWithPermission(String permission) {
+ boolean hasPermission(ICommandSender sender, String permission) {
+ return sender.canUseCommand(4, permission);
+ }
+
+ @Override
+ public Set<CommandSender> getSendersWithPermission(String permission) {
MinecraftServer mcServer = FMLCommonHandler.instance().getMinecraftServerInstance();
- Set<ICommandSender> senders = new HashSet<>(mcServer.getPlayerList().getPlayers());
+ List<ICommandSender> senders = new LinkedList<>(mcServer.getPlayerList().getPlayers());
senders.removeIf(sender -> !sender.canUseCommand(4, permission));
senders.add(mcServer);
- return senders;
+ return senders.stream().map(sender -> new ForgeCommandSender(sender, this)).collect(Collectors.toSet());
}
@Override
@@ -64,9 +71,4 @@ public class ForgeServerSparkPlugin extends ForgeSparkPlugin {
public List<String> getAliases() {
return Collections.emptyList();
}
-
- @Override
- public boolean checkPermission(MinecraftServer server, ICommandSender sender) {
- return sender.canUseCommand(4, "spark");
- }
}
diff --git a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeSparkPlugin.java b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeSparkPlugin.java
index 7298793..039a7de 100644
--- a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeSparkPlugin.java
+++ b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeSparkPlugin.java
@@ -24,43 +24,36 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
import me.lucko.spark.common.SparkPlatform;
import me.lucko.spark.common.SparkPlugin;
import me.lucko.spark.common.sampler.ThreadDumper;
-import net.kyori.text.Component;
-import net.kyori.text.TextComponent;
-import net.kyori.text.serializer.ComponentSerializers;
import net.minecraft.command.ICommand;
import net.minecraft.command.ICommandSender;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.math.BlockPos;
-import net.minecraft.util.text.ITextComponent;
-import net.minecraft.util.text.Style;
-import net.minecraft.util.text.TextComponentString;
-import net.minecraft.util.text.TextFormatting;
-import net.minecraft.util.text.event.ClickEvent;
import net.minecraftforge.fml.common.Mod;
import javax.annotation.Nullable;
import java.nio.file.Path;
-import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@SuppressWarnings("NullableProblems")
-public abstract class ForgeSparkPlugin implements SparkPlugin<ICommandSender>, ICommand {
+public abstract class ForgeSparkPlugin implements SparkPlugin, ICommand {
private final SparkForgeMod mod;
private final ScheduledExecutorService scheduler;
- private final SparkPlatform<ICommandSender> platform;
+ private final SparkPlatform platform;
protected ForgeSparkPlugin(SparkForgeMod mod) {
this.mod = mod;
this.scheduler = Executors.newSingleThreadScheduledExecutor(
new ThreadFactoryBuilder().setNameFormat("spark-forge-async-worker").build()
);
- this.platform = new SparkPlatform<>(this);
+ this.platform = new SparkPlatform(this);
this.platform.enable();
}
+ abstract boolean hasPermission(ICommandSender sender, String permission);
+
@Override
public String getVersion() {
return SparkForgeMod.class.getAnnotation(Mod.class).version();
@@ -72,12 +65,6 @@ public abstract class ForgeSparkPlugin implements SparkPlugin<ICommandSender>, I
}
@Override
- public void sendMessage(ICommandSender sender, Component message) {
- ITextComponent component = ITextComponent.Serializer.jsonToComponent(ComponentSerializers.JSON.serialize(message));
- sender.sendMessage(component);
- }
-
- @Override
public void runAsync(Runnable r) {
this.scheduler.execute(r);
}
@@ -96,25 +83,17 @@ public abstract class ForgeSparkPlugin implements SparkPlugin<ICommandSender>, I
@Override
public void execute(MinecraftServer server, ICommandSender sender, String[] args) {
- if (!checkPermission(server, sender)) {
- TextComponentString msg = new TextComponentString("You do not have permission to use this command.");
- Style style = msg.getStyle();
- style.setColor(TextFormatting.GRAY);
- msg.setStyle(style);
-
- sender.sendMessage(msg);
- return;
- }
-
- this.platform.executeCommand(sender, args);
+ this.platform.executeCommand(new ForgeCommandSender(sender, this), args);
}
@Override
public List<String> getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, @Nullable BlockPos blockPos) {
- if (!checkPermission(server, sender)) {
- return Collections.emptyList();
- }
- return this.platform.tabCompleteCommand(sender, args);
+ return this.platform.tabCompleteCommand(new ForgeCommandSender(sender, this), args);
+ }
+
+ @Override
+ public boolean checkPermission(MinecraftServer minecraftServer, ICommandSender sender) {
+ return hasPermission(sender, "spark");
}
@Override
diff --git a/spark-sponge/build.gradle b/spark-sponge/build.gradle
index dee1aac..3fd93e2 100644
--- a/spark-sponge/build.gradle
+++ b/spark-sponge/build.gradle
@@ -4,7 +4,9 @@ plugins {
dependencies {
compile project(':spark-common')
- compile 'net.kyori:text-adapter-spongeapi:1.0.3'
+ compile('net.kyori:text-adapter-spongeapi:1.0.3') {
+ exclude(module: 'text')
+ }
compileOnly 'org.spongepowered:spongeapi:7.1.0'
annotationProcessor 'org.spongepowered:spongeapi:7.1.0'
}
diff --git a/spark-sponge/src/main/java/me/lucko/spark/sponge/SparkSpongePlugin.java b/spark-sponge/src/main/java/me/lucko/spark/sponge/SparkSpongePlugin.java
index c0727ac..537bfea 100644
--- a/spark-sponge/src/main/java/me/lucko/spark/sponge/SparkSpongePlugin.java
+++ b/spark-sponge/src/main/java/me/lucko/spark/sponge/SparkSpongePlugin.java
@@ -21,12 +21,11 @@
package me.lucko.spark.sponge;
import com.google.inject.Inject;
+import me.lucko.spark.common.CommandSender;
import me.lucko.spark.common.SparkPlatform;
import me.lucko.spark.common.SparkPlugin;
import me.lucko.spark.common.sampler.ThreadDumper;
import me.lucko.spark.common.sampler.TickCounter;
-import net.kyori.text.Component;
-import net.kyori.text.adapter.spongeapi.TextAdapter;
import org.spongepowered.api.Game;
import org.spongepowered.api.command.CommandCallable;
import org.spongepowered.api.command.CommandResult;
@@ -40,21 +39,16 @@ import org.spongepowered.api.plugin.Plugin;
import org.spongepowered.api.scheduler.AsynchronousExecutor;
import org.spongepowered.api.scheduler.SpongeExecutorService;
import org.spongepowered.api.text.Text;
-import org.spongepowered.api.text.action.TextActions;
-import org.spongepowered.api.text.format.TextColors;
-import org.spongepowered.api.text.serializer.TextSerializers;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;
import javax.annotation.Nullable;
-import java.net.MalformedURLException;
-import java.net.URL;
import java.nio.file.Path;
-import java.util.Collections;
-import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
@Plugin(
id = "spark",
@@ -67,13 +61,13 @@ import java.util.Set;
@Dependency(id = "spongeapi")
}
)
-public class SparkSpongePlugin implements SparkPlugin<CommandSource> {
+public class SparkSpongePlugin implements SparkPlugin {
private final Game game;
private final Path configDirectory;
private final SpongeExecutorService asyncExecutor;
- private final SparkPlatform<CommandSource> platform = new SparkPlatform<>(this);
+ private final SparkPlatform platform = new SparkPlatform(this);
@Inject
public SparkSpongePlugin(Game game, @ConfigDir(sharedRoot = false) Path configDirectory, @AsynchronousExecutor SpongeExecutorService asyncExecutor) {
@@ -109,16 +103,11 @@ public class SparkSpongePlugin implements SparkPlugin<CommandSource> {
}
@Override
- public Set<CommandSource> getSendersWithPermission(String permission) {
- Set<CommandSource> senders = new HashSet<>(this.game.getServer().getOnlinePlayers());
+ public Set<CommandSender> getSendersWithPermission(String permission) {
+ List<CommandSource> senders = new LinkedList<>(this.game.getServer().getOnlinePlayers());
senders.removeIf(sender -> !sender.hasPermission(permission));
senders.add(this.game.getServer().getConsole());
- return senders;
- }
-
- @Override
- public void sendMessage(CommandSource sender, Component message) {
- TextAdapter.sendComponent(sender, message);
+ return senders.stream().map(SpongeCommandSender::new).collect(Collectors.toSet());
}
@Override
@@ -145,18 +134,13 @@ public class SparkSpongePlugin implements SparkPlugin<CommandSource> {
@Override
public CommandResult process(CommandSource source, String arguments) {
- if (!testPermission(source)) {
- source.sendMessage(Text.builder("You do not have permission to use this command.").color(TextColors.RED).build());
- return CommandResult.empty();
- }
-
- this.plugin.platform.executeCommand(source, arguments.split(" "));
+ this.plugin.platform.executeCommand(new SpongeCommandSender(source), arguments.split(" "));
return CommandResult.empty();
}
@Override
public List<String> getSuggestions(CommandSource source, String arguments, @Nullable Location<World> targetPosition) {
- return Collections.emptyList();
+ return this.plugin.platform.tabCompleteCommand(new SpongeCommandSender(source), arguments.split(" "));
}
@Override
diff --git a/spark-sponge/src/main/java/me/lucko/spark/sponge/SpongeCommandSender.java b/spark-sponge/src/main/java/me/lucko/spark/sponge/SpongeCommandSender.java
new file mode 100644
index 0000000..5b434fc
--- /dev/null
+++ b/spark-sponge/src/main/java/me/lucko/spark/sponge/SpongeCommandSender.java
@@ -0,0 +1,62 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.sponge;
+
+import me.lucko.spark.common.CommandSender;
+import net.kyori.text.Component;
+import net.kyori.text.adapter.spongeapi.TextAdapter;
+import org.spongepowered.api.command.CommandSource;
+
+public class SpongeCommandSender implements CommandSender {
+ private final CommandSource source;
+
+ public SpongeCommandSender(CommandSource source) {
+ this.source = source;
+ }
+
+ @Override
+ public String getName() {
+ return this.source.getName();
+ }
+
+ @Override
+ public void sendMessage(Component message) {
+ TextAdapter.sendComponent(this.source, message);
+ }
+
+ @Override
+ public boolean hasPermission(String permission) {
+ return this.source.hasPermission(permission);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SpongeCommandSender that = (SpongeCommandSender) o;
+ return this.source.equals(that.source);
+ }
+
+ @Override
+ public int hashCode() {
+ return this.source.hashCode();
+ }
+}
diff --git a/spark-velocity/src/main/java/me/lucko/spark/velocity/SparkVelocityPlugin.java b/spark-velocity/src/main/java/me/lucko/spark/velocity/SparkVelocityPlugin.java
index c1c2f2d..4a5f500 100644
--- a/spark-velocity/src/main/java/me/lucko/spark/velocity/SparkVelocityPlugin.java
+++ b/spark-velocity/src/main/java/me/lucko/spark/velocity/SparkVelocityPlugin.java
@@ -30,21 +30,19 @@ import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.ProxyServer;
+import me.lucko.spark.common.CommandSender;
import me.lucko.spark.common.SparkPlatform;
import me.lucko.spark.common.SparkPlugin;
import me.lucko.spark.common.sampler.ThreadDumper;
import me.lucko.spark.common.sampler.TickCounter;
-import net.kyori.text.Component;
-import net.kyori.text.TextComponent;
-import net.kyori.text.event.ClickEvent;
-import net.kyori.text.format.TextColor;
-import net.kyori.text.serializer.ComponentSerializers;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.optional.qual.MaybePresent;
import java.nio.file.Path;
-import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
@Plugin(
id = "spark",
@@ -53,9 +51,9 @@ import java.util.Set;
description = "@desc@",
authors = {"Luck", "sk89q"}
)
-public class SparkVelocityPlugin implements SparkPlugin<CommandSource>, Command {
+public class SparkVelocityPlugin implements SparkPlugin, Command {
- private final SparkPlatform<CommandSource> platform = new SparkPlatform<>(this);
+ private final SparkPlatform platform = new SparkPlatform(this);
private final ProxyServer proxy;
private final Path configDirectory;
@@ -79,13 +77,12 @@ public class SparkVelocityPlugin implements SparkPlugin<CommandSource>, Command
@Override
public void execute(@MaybePresent CommandSource sender, @NonNull @MaybePresent String[] args) {
- if (!sender.hasPermission("spark")) {
- TextComponent msg = TextComponent.builder("You do not have permission to use this command.").color(TextColor.RED).build();
- sender.sendMessage(msg);
- return;
- }
+ this.platform.executeCommand(new VelocityCommandSender(sender), args);
+ }
- this.platform.executeCommand(sender, args);
+ @Override
+ public @MaybePresent List<String> suggest(@MaybePresent CommandSource sender, @NonNull @MaybePresent String[] currentArgs) {
+ return this.platform.tabCompleteCommand(new VelocityCommandSender(sender), currentArgs);
}
@Override
@@ -104,16 +101,11 @@ public class SparkVelocityPlugin implements SparkPlugin<CommandSource>, Command
}
@Override
- public Set<CommandSource> getSendersWithPermission(String permission) {
- Set<CommandSource> senders = new HashSet<>(this.proxy.getAllPlayers());
+ public Set<CommandSender> getSendersWithPermission(String permission) {
+ List<CommandSource> senders = new LinkedList<>(this.proxy.getAllPlayers());
senders.removeIf(sender -> !sender.hasPermission(permission));
senders.add(this.proxy.getConsoleCommandSource());
- return senders;
- }
-
- @Override
- public void sendMessage(CommandSource sender, Component message) {
- sender.sendMessage(message);
+ return senders.stream().map(VelocityCommandSender::new).collect(Collectors.toSet());
}
@Override
diff --git a/spark-velocity/src/main/java/me/lucko/spark/velocity/VelocityCommandSender.java b/spark-velocity/src/main/java/me/lucko/spark/velocity/VelocityCommandSender.java
new file mode 100644
index 0000000..1cad493
--- /dev/null
+++ b/spark-velocity/src/main/java/me/lucko/spark/velocity/VelocityCommandSender.java
@@ -0,0 +1,69 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.velocity;
+
+import com.velocitypowered.api.command.CommandSource;
+import com.velocitypowered.api.proxy.ConsoleCommandSource;
+import com.velocitypowered.api.proxy.Player;
+import me.lucko.spark.common.CommandSender;
+import net.kyori.text.Component;
+
+public class VelocityCommandSender implements CommandSender {
+ private final CommandSource source;
+
+ public VelocityCommandSender(CommandSource source) {
+ this.source = source;
+ }
+
+ @Override
+ public String getName() {
+ if (this.source instanceof Player) {
+ return ((Player) this.source).getUsername();
+ } else if (this.source instanceof ConsoleCommandSource) {
+ return "Console";
+ } else {
+ return "unknown:" + this.source.getClass().getSimpleName();
+ }
+ }
+
+ @Override
+ public void sendMessage(Component message) {
+ this.source.sendMessage(message);
+ }
+
+ @Override
+ public boolean hasPermission(String permission) {
+ return this.source.hasPermission(permission);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ VelocityCommandSender that = (VelocityCommandSender) o;
+ return this.source.equals(that.source);
+ }
+
+ @Override
+ public int hashCode() {
+ return this.source.hashCode();
+ }
+}