diff options
13 files changed, 387 insertions, 7 deletions
diff --git a/settings.gradle b/settings.gradle index 13da274..a6d6799 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,2 @@ rootProject.name = 'spark' -include 'spark-common', 'spark-bukkit', 'spark-bungeecord', 'spark-sponge', 'spark-universal'
\ No newline at end of file +include 'spark-common', 'spark-bukkit', 'spark-bungeecord', 'spark-sponge', 'spark-universal', 'spark-forge'
\ No newline at end of file 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 dc432c5..c4b87b8 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 @@ -28,6 +28,11 @@ public class SparkBukkitPlugin extends JavaPlugin { } @Override + protected String getLabel() { + return "spark"; + } + + @Override protected void sendMessage(CommandSender sender, String message) { sender.sendMessage(colorize(message)); } 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 59bab67..9ebe145 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 @@ -30,6 +30,11 @@ public class SparkBungeeCordPlugin extends Plugin { } @Override + protected String getLabel() { + return "sparkbungee"; + } + + @Override protected void sendMessage(CommandSender sender, String message) { sender.sendMessage(colorize(message)); } diff --git a/spark-common/build.gradle b/spark-common/build.gradle index d59ce24..453bbdd 100644 --- a/spark-common/build.gradle +++ b/spark-common/build.gradle @@ -1,6 +1,5 @@ dependencies { compile 'com.squareup.okhttp3:okhttp:3.10.0' - compile 'com.squareup.okio:okio:1.14.0' 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/CommandHandler.java b/spark-common/src/main/java/me/lucko/spark/common/CommandHandler.java index 898bba7..72774d5 100644 --- a/spark-common/src/main/java/me/lucko/spark/common/CommandHandler.java +++ b/spark-common/src/main/java/me/lucko/spark/common/CommandHandler.java @@ -51,6 +51,7 @@ public abstract class CommandHandler<T> { // abstract methods implemented by each platform + protected abstract String getLabel(); protected abstract void sendMessage(T sender, String message); protected abstract void sendMessage(String message); protected abstract void sendLink(String url); @@ -103,16 +104,16 @@ public abstract class CommandHandler<T> { private void sendInfo(T sender) { sendPrefixedMessage(sender, "&fspark profiler &7v1.0"); - sendMessage(sender, "&b&l> &7/profiler start"); + sendMessage(sender, "&b&l> &7/" + getLabel() + " start"); sendMessage(sender, " &8[&7--timeout&8 <timeout seconds>]"); sendMessage(sender, " &8[&7--thread&8 <thread name>]"); sendMessage(sender, " &8[&7--not-combined]"); sendMessage(sender, " &8[&7--interval&8 <interval millis>]"); sendMessage(sender, " &8[&7--only-ticks-over&8 <tick length millis>]"); - sendMessage(sender, "&b&l> &7/profiler info"); - sendMessage(sender, "&b&l> &7/profiler stop"); - sendMessage(sender, "&b&l> &7/profiler cancel"); - sendMessage(sender, "&b&l> &7/profiler monitoring"); + sendMessage(sender, "&b&l> &7/" + getLabel() + " info"); + sendMessage(sender, "&b&l> &7/" + getLabel() + " stop"); + sendMessage(sender, "&b&l> &7/" + getLabel() + " cancel"); + sendMessage(sender, "&b&l> &7/" + getLabel() + " monitoring"); sendMessage(sender, " &8[&7--threshold&8 <percentage increase>]"); } diff --git a/spark-forge/build.gradle b/spark-forge/build.gradle new file mode 100644 index 0000000..68322c3 --- /dev/null +++ b/spark-forge/build.gradle @@ -0,0 +1,60 @@ +buildscript { + repositories { + jcenter() + maven { url = "http://files.minecraftforge.net/maven" } + } + dependencies { + classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT' + classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.4' + } +} + +apply plugin: 'net.minecraftforge.gradle.forge' +apply plugin: 'com.github.johnrengelman.shadow' + +minecraft { + version = '1.12.2-14.23.4.2705' + runDir = 'run' + mappings = 'snapshot_20171003' + + replaceIn 'me/lucko/spark/forge/SparkForgeMod.java' + replace '@version@', project.pluginVersion +} + +processResources { + from(sourceSets.main.resources.srcDirs) { + expand 'pluginVersion': project.pluginVersion + include 'mcmod.info' + } +} + +dependencies { + compile project(':spark-common') + + def textWithoutLibs = { + exclude group: 'com.google.code.gson', module: 'gson' + exclude group: 'com.google.guava', module: 'guava' + exclude group: 'net.kyori', module: 'blizzard' + } + + compile 'net.kyori:text:1.11-1.4.0', textWithoutLibs +} + +shadowJar { + archiveName = 'spark-forge.jar' + + relocate 'okio', 'me.lucko.spark.lib.okio' + relocate 'okhttp3', 'me.lucko.spark.lib.okhttp3' + relocate 'net.kyori.text', 'me.lucko.spark.lib.text' +} + +artifacts { + archives shadowJar + shadow shadowJar +} + +reobf { + shadowJar { + mappingType = 'SEARGE' + } +} diff --git a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeClientCommandHandler.java b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeClientCommandHandler.java new file mode 100644 index 0000000..5fbf524 --- /dev/null +++ b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeClientCommandHandler.java @@ -0,0 +1,43 @@ +package me.lucko.spark.forge; + +import me.lucko.spark.profiler.TickCounter; + +import net.minecraft.client.Minecraft; +import net.minecraft.util.text.ITextComponent; +import net.minecraftforge.client.ClientCommandHandler; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.Collections; +import java.util.List; + +public class ForgeClientCommandHandler extends ForgeCommandHandler { + + public static void register() { + ClientCommandHandler.instance.registerCommand(new ForgeClientCommandHandler()); + } + + @Override + protected void broadcast(ITextComponent msg) { + Minecraft.getMinecraft().player.sendMessage(msg); + } + + @Override + protected TickCounter newTickCounter() { + return new ForgeTickCounter(TickEvent.Type.CLIENT); + } + + @Override + public String getLabel() { + return "sparkclient"; + } + + @Override + public String getName() { + return "sparkclient"; + } + + @Override + public List<String> getAliases() { + return Collections.singletonList("cprofiler"); + } +} diff --git a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeCommandHandler.java b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeCommandHandler.java new file mode 100644 index 0000000..63ec201 --- /dev/null +++ b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeCommandHandler.java @@ -0,0 +1,116 @@ +package me.lucko.spark.forge; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; + +import me.lucko.spark.common.CommandHandler; +import me.lucko.spark.profiler.ThreadDumper; + +import net.kyori.text.TextComponent; +import net.kyori.text.serializer.ComponentSerializers; +import net.minecraft.command.CommandException; +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 java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import javax.annotation.Nullable; + +@SuppressWarnings("NullableProblems") +public abstract class ForgeCommandHandler extends CommandHandler<ICommandSender> implements ICommand { + + private final ExecutorService worker = Executors.newSingleThreadExecutor( + new ThreadFactoryBuilder().setNameFormat("spark-forge-async-worker").build() + ); + + @SuppressWarnings("deprecation") + protected ITextComponent colorize(String message) { + TextComponent component = ComponentSerializers.LEGACY.deserialize(message, '&'); + return ITextComponent.Serializer.jsonToComponent(ComponentSerializers.JSON.serialize(component)); + } + + protected abstract void broadcast(ITextComponent msg); + + @Override + protected void sendMessage(ICommandSender sender, String message) { + sender.sendMessage(colorize(message)); + } + + @Override + protected void sendMessage(String message) { + ITextComponent msg = colorize(message); + broadcast(msg); + } + + @Override + protected void sendLink(String url) { + TextComponentString msg = new TextComponentString(url); + Style style = msg.getStyle(); + style.setColor(TextFormatting.GRAY); + style.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url)); + msg.setStyle(style); + + broadcast(msg); + } + + @Override + protected void runAsync(Runnable r) { + worker.execute(r); + } + + @Override + protected ThreadDumper getDefaultThreadDumper() { + return new ThreadDumper.Specific(new long[]{Thread.currentThread().getId()}); + } + + // implement ICommand + + @Override + public String getUsage(ICommandSender iCommandSender) { + return "/" + getLabel(); + } + + @Override + public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { + 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; + } + + handleCommand(sender, args); + } + + @Override + public boolean checkPermission(MinecraftServer server, ICommandSender sender) { + return sender.canUseCommand(4, "spark.profiler"); + } + + @Override + public List<String> getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, @Nullable BlockPos blockPos) { + return Collections.emptyList(); + } + + @Override + public boolean isUsernameIndex(String[] strings, int i) { + return false; + } + + @Override + public int compareTo(ICommand o) { + return getLabel().compareTo(o.getName()); + } +} diff --git a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeServerCommandHandler.java b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeServerCommandHandler.java new file mode 100644 index 0000000..40c4989 --- /dev/null +++ b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeServerCommandHandler.java @@ -0,0 +1,46 @@ +package me.lucko.spark.forge; + +import me.lucko.spark.profiler.TickCounter; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.text.ITextComponent; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.Collections; +import java.util.List; + +public class ForgeServerCommandHandler extends ForgeCommandHandler { + + @Override + protected void broadcast(ITextComponent msg) { + FMLCommonHandler.instance().getMinecraftServerInstance().sendMessage(msg); + + List<EntityPlayerMP> players = FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().getPlayers(); + for (EntityPlayerMP player : players) { + if (player.canUseCommand(4, "spark.profiler")) { + player.sendMessage(msg); + } + } + } + + @Override + protected TickCounter newTickCounter() { + return new ForgeTickCounter(TickEvent.Type.SERVER); + } + + @Override + public String getLabel() { + return "spark"; + } + + @Override + public String getName() { + return "spark"; + } + + @Override + public List<String> getAliases() { + return Collections.singletonList("profiler"); + } +} diff --git a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeTickCounter.java b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeTickCounter.java new file mode 100644 index 0000000..b113bcf --- /dev/null +++ b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeTickCounter.java @@ -0,0 +1,63 @@ +package me.lucko.spark.forge; + +import me.lucko.spark.profiler.TickCounter; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.atomic.LongAdder; + +public class ForgeTickCounter implements TickCounter { + private final TickEvent.Type type; + + private final Set<Runnable> tasks = new HashSet<>(); + private final LongAdder tick = new LongAdder(); + + public ForgeTickCounter(TickEvent.Type type) { + this.type = type; + } + + @SubscribeEvent + public void onTick(TickEvent e) { + if (e.phase != TickEvent.Phase.END) { + return; + } + + if (e.type != this.type) { + return; + } + + this.tick.increment(); + for (Runnable r : this.tasks){ + r.run(); + } + } + + @Override + public void start() { + MinecraftForge.EVENT_BUS.register(this); + } + + @Override + public void close() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @Override + public long getCurrentTick() { + return this.tick.longValue(); + } + + @Override + public void addTickTask(Runnable runnable) { + this.tasks.add(runnable); + } + + @Override + public void removeTickTask(Runnable runnable) { + this.tasks.remove(runnable); + } +} diff --git a/spark-forge/src/main/java/me/lucko/spark/forge/SparkForgeMod.java b/spark-forge/src/main/java/me/lucko/spark/forge/SparkForgeMod.java new file mode 100644 index 0000000..39c1f6f --- /dev/null +++ b/spark-forge/src/main/java/me/lucko/spark/forge/SparkForgeMod.java @@ -0,0 +1,30 @@ +package me.lucko.spark.forge; + +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLServerStartingEvent; +import net.minecraftforge.fml.relauncher.Side; + +@Mod( + modid = "spark", + name = "spark", + version = "@version@", + acceptableRemoteVersions = "*" +) +public class SparkForgeMod { + + @EventHandler + public void init(FMLInitializationEvent e) { + if (FMLCommonHandler.instance().getSide() == Side.CLIENT) { + ForgeClientCommandHandler.register(); + } + } + + @EventHandler + public void serverInit(FMLServerStartingEvent e) { + e.registerServerCommand(new ForgeServerCommandHandler()); + } + +} diff --git a/spark-forge/src/main/resources/mcmod.info b/spark-forge/src/main/resources/mcmod.info new file mode 100644 index 0000000..88b1ccb --- /dev/null +++ b/spark-forge/src/main/resources/mcmod.info @@ -0,0 +1,7 @@ +[{ + "modid": "spark", + "name": "spark", + "description": "Spark is a CPU profiling plugin based on sk89q's WarmRoast profiler", + "version": "${pluginVersion}", + "authors": ["Luck", "sk89q"] +}]
\ No newline at end of file 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 845d2c1..bd1db87 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 @@ -56,6 +56,11 @@ public class SparkSpongePlugin implements CommandCallable { } @Override + protected String getLabel() { + return "spark"; + } + + @Override protected void sendMessage(CommandSource sender, String message) { sender.sendMessage(colorize(message)); } |