From bf2262c392c7e234c8662aa7be5d2970dcacee65 Mon Sep 17 00:00:00 2001 From: Luck Date: Mon, 26 Aug 2019 09:02:55 +0100 Subject: Various misc changes to spark-forge and spark-fabric --- spark-fabric/build.gradle | 4 +- .../spark/fabric/FabricClientSparkPlugin.java | 104 ----------------- .../me/lucko/spark/fabric/FabricCommandSender.java | 15 +-- .../spark/fabric/FabricServerSparkPlugin.java | 84 -------------- .../lucko/spark/fabric/FabricSparkGameHooks.java | 73 ++++++++++++ .../java/me/lucko/spark/fabric/FabricSparkMod.java | 77 +++---------- .../me/lucko/spark/fabric/FabricSparkPlugin.java | 89 --------------- .../me/lucko/spark/fabric/FabricTickCounter.java | 45 ++++---- .../fabric/mixin/ClientPlayerEntityMixin.java | 4 +- .../spark/fabric/mixin/MinecraftClientMixin.java | 7 +- .../spark/fabric/mixin/MinecraftServerMixin.java | 7 +- .../fabric/plugin/FabricClientSparkPlugin.java | 110 ++++++++++++++++++ .../fabric/plugin/FabricServerSparkPlugin.java | 95 +++++++++++++++ .../spark/fabric/plugin/FabricSparkPlugin.java | 94 +++++++++++++++ .../src/main/resources/assets/spark/icon.png | Bin 2932 -> 2885 bytes spark-fabric/src/main/resources/fabric.mod.json | 6 +- .../lucko/spark/forge/ForgeClientSparkPlugin.java | 124 -------------------- .../me/lucko/spark/forge/ForgeCommandSender.java | 1 + .../lucko/spark/forge/ForgeServerSparkPlugin.java | 97 ---------------- .../java/me/lucko/spark/forge/ForgeSparkMod.java | 2 + .../me/lucko/spark/forge/ForgeSparkPlugin.java | 86 -------------- .../spark/forge/plugin/ForgeClientSparkPlugin.java | 127 +++++++++++++++++++++ .../spark/forge/plugin/ForgeServerSparkPlugin.java | 100 ++++++++++++++++ .../lucko/spark/forge/plugin/ForgeSparkPlugin.java | 94 +++++++++++++++ 24 files changed, 757 insertions(+), 688 deletions(-) delete mode 100644 spark-fabric/src/main/java/me/lucko/spark/fabric/FabricClientSparkPlugin.java delete mode 100644 spark-fabric/src/main/java/me/lucko/spark/fabric/FabricServerSparkPlugin.java create mode 100644 spark-fabric/src/main/java/me/lucko/spark/fabric/FabricSparkGameHooks.java delete mode 100644 spark-fabric/src/main/java/me/lucko/spark/fabric/FabricSparkPlugin.java create mode 100644 spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricClientSparkPlugin.java create mode 100644 spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricServerSparkPlugin.java create mode 100644 spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricSparkPlugin.java delete mode 100644 spark-forge/src/main/java/me/lucko/spark/forge/ForgeClientSparkPlugin.java delete mode 100644 spark-forge/src/main/java/me/lucko/spark/forge/ForgeServerSparkPlugin.java delete mode 100644 spark-forge/src/main/java/me/lucko/spark/forge/ForgeSparkPlugin.java create mode 100644 spark-forge/src/main/java/me/lucko/spark/forge/plugin/ForgeClientSparkPlugin.java create mode 100644 spark-forge/src/main/java/me/lucko/spark/forge/plugin/ForgeServerSparkPlugin.java create mode 100644 spark-forge/src/main/java/me/lucko/spark/forge/plugin/ForgeSparkPlugin.java diff --git a/spark-fabric/build.gradle b/spark-fabric/build.gradle index ca0ce24..7640be2 100644 --- a/spark-fabric/build.gradle +++ b/spark-fabric/build.gradle @@ -1,3 +1,5 @@ +import net.fabricmc.loom.task.RemapJarTask + plugins { id 'fabric-loom' version '0.2.5-SNAPSHOT' id 'com.github.johnrengelman.shadow' version '4.0.1' @@ -40,7 +42,7 @@ shadowJar { relocate 'com.google.protobuf', 'me.lucko.spark.lib.protobuf' } -task remappedShadowJar(type: net.fabricmc.loom.task.RemapJarTask) { +task remappedShadowJar(type: RemapJarTask) { dependsOn tasks.shadowJar input = tasks.shadowJar.archiveFile addNestedDependencies = true diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricClientSparkPlugin.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricClientSparkPlugin.java deleted file mode 100644 index 1421779..0000000 --- a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricClientSparkPlugin.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This file is part of spark. - * - * Copyright (c) lucko (Luck) - * 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 . - */ - -package me.lucko.spark.fabric; - -import com.mojang.brigadier.CommandDispatcher; -import me.lucko.spark.common.sampler.TickCounter; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.server.command.CommandSource; - -import java.util.Arrays; -import java.util.concurrent.TimeUnit; -import java.util.stream.Stream; - -public class FabricClientSparkPlugin extends FabricSparkPlugin { - - private final MinecraftClient minecraft; - private CommandDispatcher dispatcher; - - public FabricClientSparkPlugin(FabricSparkMod mod, MinecraftClient minecraft) { - super(mod); - this.minecraft = minecraft; - } - - public static void register(FabricSparkMod mod, MinecraftClient client) { - FabricClientSparkPlugin plugin = new FabricClientSparkPlugin(mod, client); - - plugin.scheduler.scheduleWithFixedDelay(plugin::checkCommandRegistered, 10, 10, TimeUnit.SECONDS); - } - - private void checkCommandRegistered() { - ClientPlayerEntity player = this.minecraft.player; - if (player == null) { - return; - } - - ClientPlayNetworkHandler connection = player.networkHandler; - if (connection == null) { - return; - } - - try { - CommandDispatcher dispatcher = connection.getCommandDispatcher(); - if (dispatcher != this.dispatcher) { - this.dispatcher = dispatcher; - registerCommands(this.dispatcher, c -> 0, "sparkc", "sparkclient"); - this.mod.setChatSendCallback(this::onClientChat); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - private FabricCommandSender createClientSender() { - return new FabricCommandSender(this.minecraft.player.networkHandler.getCommandSource()::hasPermissionLevel, this.minecraft.player); - } - - public boolean onClientChat(String chat) { - String[] split = chat.split(" "); - if (split.length == 0 || (!split[0].equals("/sparkc") && !split[0].equals("/sparkclient"))) { - return false; - } - - String[] args = Arrays.copyOfRange(split, 1, split.length); - this.platform.executeCommand(createClientSender(), args); - this.minecraft.inGameHud.getChatHud().addToMessageHistory(chat); - return true; - } - - @Override - public Stream getSendersWithPermission(String permission) { - return Stream.of(createClientSender()); - } - - @Override - public TickCounter createTickCounter() { - return new FabricTickCounter(FabricSparkMod.getInstance()::addClientCounter, FabricSparkMod.getInstance()::removeClientCounter); - } - - @Override - public String getCommandName() { - return "sparkc"; - } - -} diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricCommandSender.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricCommandSender.java index 3a8d128..fea877c 100644 --- a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricCommandSender.java +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricCommandSender.java @@ -21,6 +21,7 @@ package me.lucko.spark.fabric; import me.lucko.spark.common.CommandSender; +import me.lucko.spark.fabric.plugin.FabricSparkPlugin; import net.kyori.text.Component; import net.kyori.text.serializer.gson.GsonComponentSerializer; import net.minecraft.entity.player.PlayerEntity; @@ -31,13 +32,12 @@ import net.minecraft.text.Text; import java.util.UUID; public class FabricCommandSender implements CommandSender { - - private final VanillaPermission permission; private final CommandOutput sender; + private final FabricSparkPlugin plugin; - public FabricCommandSender(VanillaPermission permission, CommandOutput sender) { - this.permission = permission; + public FabricCommandSender(CommandOutput sender, FabricSparkPlugin plugin) { this.sender = sender; + this.plugin = plugin; } @Override @@ -67,7 +67,7 @@ public class FabricCommandSender implements CommandSender { @Override public boolean hasPermission(String permission) { - return this.permission.hasPermissionLevel(4); // Require /stop access, reasonable + return this.plugin.hasPermission(this.sender, permission); } @Override @@ -86,9 +86,4 @@ public class FabricCommandSender implements CommandSender { public int hashCode() { return this.sender.hashCode(); } - - public interface VanillaPermission { - - boolean hasPermissionLevel(int level); - } } diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricServerSparkPlugin.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricServerSparkPlugin.java deleted file mode 100644 index 01bc442..0000000 --- a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricServerSparkPlugin.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is part of spark. - * - * Copyright (c) lucko (Luck) - * 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 . - */ - -package me.lucko.spark.fabric; - -import com.mojang.brigadier.Command; -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import me.lucko.spark.common.sampler.TickCounter; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.LiteralText; - -import java.util.Arrays; -import java.util.stream.Stream; - -public class FabricServerSparkPlugin extends FabricSparkPlugin implements Command { - - private final MinecraftServer server; - - public FabricServerSparkPlugin(FabricSparkMod mod, MinecraftServer server) { - super(mod); - this.server = server; - } - - public static void register(FabricSparkMod mod, MinecraftServer server) { - CommandDispatcher dispatcher = server.getCommandManager().getDispatcher(); - - FabricServerSparkPlugin plugin = new FabricServerSparkPlugin(mod, server); - registerCommands(dispatcher, plugin, "spark"); - // PermissionAPI.registerNode("spark", DefaultPermissionLevel.OP, "Access to the spark command"); - } - - @Override - public int run(CommandContext context) throws CommandSyntaxException { - String[] split = context.getInput().split(" "); - if (split.length == 0 || !split[0].equals("/spark")) { - context.getSource().sendError(new LiteralText("Wrong split started with " + (split.length == 0 ? "nothing" : split[0]))); - return 0; - } - - String[] args = Arrays.copyOfRange(split, 1, split.length); - - this.platform.executeCommand(new FabricCommandSender(context.getSource()::hasPermissionLevel, context.getSource().getPlayer()), args); - return 1; - } - - @Override - public Stream getSendersWithPermission(String permission) { - return Stream.concat( - this.server.getPlayerManager().getPlayerList().stream() - .filter(player -> this.server.getPermissionLevel(player.getGameProfile()) == 4), - Stream.of(this.server) - ).map(sender -> new FabricCommandSender(i -> true, sender)); - } - - @Override - public TickCounter createTickCounter() { - return new FabricTickCounter(FabricSparkMod.getInstance()::addServerCounter, FabricSparkMod.getInstance()::removeServerCounter); - } - - @Override - public String getCommandName() { - return "spark"; - } -} diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricSparkGameHooks.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricSparkGameHooks.java new file mode 100644 index 0000000..d046ab8 --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricSparkGameHooks.java @@ -0,0 +1,73 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) + * 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 . + */ + +package me.lucko.spark.fabric; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.Predicate; + +public enum FabricSparkGameHooks { + INSTANCE; + + private final Set clientCounters = new HashSet<>(); + private final Set serverCounters = new HashSet<>(); + + // Use events from Fabric API later + // Return true to abort sending to server + private Predicate chatSendCallback = s -> false; + + public void setChatSendCallback(Predicate callback) { + this.chatSendCallback = callback; + } + + public boolean tryProcessChat(String message) { + return this.chatSendCallback.test(message); + } + + public void addClientCounter(FabricTickCounter counter) { + this.clientCounters.add(counter); + } + + public void removeClientCounter(FabricTickCounter counter) { + this.clientCounters.remove(counter); + } + + public void addServerCounter(FabricTickCounter counter) { + this.serverCounters.add(counter); + } + + public void removeServerCounter(FabricTickCounter counter) { + this.serverCounters.remove(counter); + } + + public void tickClientCounters() { + for (FabricTickCounter counter : this.clientCounters) { + counter.onTick(); + } + } + + public void tickServerCounters() { + for (FabricTickCounter counter : this.serverCounters) { + counter.onTick(); + } + } + +} diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricSparkMod.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricSparkMod.java index 4e4468b..0f6fb1f 100644 --- a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricSparkMod.java +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricSparkMod.java @@ -22,85 +22,38 @@ package me.lucko.spark.fabric; import net.fabricmc.api.ModInitializer; import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.ModContainer; import java.nio.file.Path; -import java.util.HashSet; -import java.util.Set; -import java.util.function.Predicate; public class FabricSparkMod implements ModInitializer { + private static FabricSparkMod mod; - private static FabricSparkMod instance; - private final Set clientCounters = new HashSet<>(); - private final Set serverCounters = new HashSet<>(); - private String version; - private Path configDir; - // Use events from Fabric API later - // Return true to abort sending to server - private Predicate chatSendCallback = s -> false; - - public FabricSparkMod() { + public static FabricSparkMod getMod() { + return mod; } - public static FabricSparkMod getInstance() { - return instance; - } + private ModContainer container; + private Path configDirectory; @Override public void onInitialize() { - FabricSparkMod.instance = this; - FabricLoader loader = FabricLoader.getInstance(); - this.version = loader.getModContainer("spark") - .orElseThrow(() -> new IllegalStateException("Spark loaded incorrectly!")) - .getMetadata() - .getVersion() - .getFriendlyString(); - this.configDir = loader.getConfigDirectory().toPath().resolve("spark"); + FabricSparkMod.mod = this; - // When Fabric API is available, we will register event listeners here + FabricLoader loader = FabricLoader.getInstance(); + this.container = loader.getModContainer("spark") + .orElseThrow(() -> new IllegalStateException("Unable to get container for spark")); + this.configDirectory = loader.getConfigDirectory().toPath().resolve("spark"); } public String getVersion() { - return version; + return this.container.getMetadata().getVersion().getFriendlyString(); } public Path getConfigDirectory() { - return configDir; - } - - public void setChatSendCallback(Predicate callback) { - this.chatSendCallback = callback; - } - - public boolean tryProcessChat(String message) { - return chatSendCallback.test(message); - } - - public void addClientCounter(FabricTickCounter counter) { - this.clientCounters.add(counter); - } - - public void removeClientCounter(FabricTickCounter counter) { - this.clientCounters.remove(counter); - } - - public void addServerCounter(FabricTickCounter counter) { - this.serverCounters.add(counter); - } - - public void removeServerCounter(FabricTickCounter counter) { - this.serverCounters.remove(counter); - } - - public void tickClientCounters() { - for (FabricTickCounter each : clientCounters) { - each.onTick(); - } - } - - public void tickServerCounters() { - for (FabricTickCounter each : serverCounters) { - each.onTick(); + if (this.configDirectory == null) { + throw new IllegalStateException("Config directory not set"); } + return this.configDirectory; } } diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricSparkPlugin.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricSparkPlugin.java deleted file mode 100644 index a0f6cf0..0000000 --- a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricSparkPlugin.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This file is part of spark. - * - * Copyright (c) lucko (Luck) - * 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 . - */ - -package me.lucko.spark.fabric; - -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.mojang.brigadier.Command; -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import com.mojang.brigadier.tree.LiteralCommandNode; -import me.lucko.spark.common.SparkPlatform; -import me.lucko.spark.common.SparkPlugin; -import me.lucko.spark.common.sampler.ThreadDumper; - -import java.nio.file.Path; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; - -public abstract class FabricSparkPlugin implements SparkPlugin { - - protected final ScheduledExecutorService scheduler; - protected final SparkPlatform platform; - protected final FabricSparkMod mod; - - protected FabricSparkPlugin(FabricSparkMod mod) { - this.mod = mod; - this.scheduler = Executors.newSingleThreadScheduledExecutor( - new ThreadFactoryBuilder().setNameFormat("spark-fabric-async-worker").build() - ); - this.platform = new SparkPlatform(this); - this.platform.enable(); - } - - public static void registerCommands(CommandDispatcher dispatcher, Command executor, String... aliases) { - if (aliases.length == 0) { - return; - } - String mainName = aliases[0]; - LiteralArgumentBuilder command = LiteralArgumentBuilder.literal(mainName) - .executes(executor) - .then(RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()) - .executes(executor) - ); - - LiteralCommandNode node = dispatcher.register(command); - for (int i = 1; i < aliases.length; i++) { - dispatcher.register(LiteralArgumentBuilder.literal(aliases[i]).redirect(node)); - } - } - - @Override - public String getVersion() { - return this.mod.getVersion(); - } - - @Override - public Path getPluginDirectory() { - return this.mod.getConfigDirectory(); - } - - @Override - public void executeAsync(Runnable task) { - this.scheduler.execute(task); - } - - @Override - public ThreadDumper getDefaultThreadDumper() { - return new ThreadDumper.Specific(new long[]{Thread.currentThread().getId()}); - } -} diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricTickCounter.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricTickCounter.java index 03d00b2..b189e3f 100644 --- a/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricTickCounter.java +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricTickCounter.java @@ -24,20 +24,11 @@ import me.lucko.spark.common.sampler.TickCounter; import java.util.HashSet; import java.util.Set; -import java.util.function.Consumer; - -public class FabricTickCounter implements TickCounter { +public abstract class FabricTickCounter implements TickCounter { private final Set tasks = new HashSet<>(); - private final Consumer adder; - private final Consumer remover; private int tick = 0; - public FabricTickCounter(Consumer adder, Consumer remover) { - this.adder = adder; - this.remover = remover; - } - public void onTick() { for (TickTask r : this.tasks) { r.onTick(this); @@ -45,16 +36,6 @@ public class FabricTickCounter implements TickCounter { this.tick++; } - @Override - public void start() { - this.adder.accept(this); - } - - @Override - public void close() { - this.remover.accept(this); - } - @Override public int getCurrentTick() { return this.tick; @@ -69,4 +50,28 @@ public class FabricTickCounter implements TickCounter { public void removeTickTask(TickTask runnable) { this.tasks.remove(runnable); } + + public static final class Server extends FabricTickCounter { + @Override + public void start() { + FabricSparkGameHooks.INSTANCE.addServerCounter(this); + } + + @Override + public void close() { + FabricSparkGameHooks.INSTANCE.removeServerCounter(this); + } + } + + public static final class Client extends FabricTickCounter { + @Override + public void start() { + FabricSparkGameHooks.INSTANCE.addClientCounter(this); + } + + @Override + public void close() { + FabricSparkGameHooks.INSTANCE.removeClientCounter(this); + } + } } diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ClientPlayerEntityMixin.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ClientPlayerEntityMixin.java index 3ce57b1..8085567 100644 --- a/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ClientPlayerEntityMixin.java +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ClientPlayerEntityMixin.java @@ -21,7 +21,7 @@ package me.lucko.spark.fabric.mixin; import com.mojang.authlib.GameProfile; -import me.lucko.spark.fabric.FabricSparkMod; +import me.lucko.spark.fabric.FabricSparkGameHooks; import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.world.ClientWorld; @@ -42,7 +42,7 @@ public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true) public void onSendChatMessage(String message, CallbackInfo ci) { - if (FabricSparkMod.getInstance().tryProcessChat(message)) { + if (FabricSparkGameHooks.INSTANCE.tryProcessChat(message)) { ci.cancel(); } } diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/MinecraftClientMixin.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/MinecraftClientMixin.java index b987ca6..ae7ef5f 100644 --- a/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/MinecraftClientMixin.java +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/MinecraftClientMixin.java @@ -20,8 +20,9 @@ package me.lucko.spark.fabric.mixin; -import me.lucko.spark.fabric.FabricClientSparkPlugin; +import me.lucko.spark.fabric.FabricSparkGameHooks; import me.lucko.spark.fabric.FabricSparkMod; +import me.lucko.spark.fabric.plugin.FabricClientSparkPlugin; import net.minecraft.client.MinecraftClient; import net.minecraft.util.NonBlockingThreadExecutor; import org.spongepowered.asm.mixin.Mixin; @@ -40,12 +41,12 @@ public abstract class MinecraftClientMixin extends NonBlockingThreadExecutor + * 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 . + */ + +package me.lucko.spark.fabric.plugin; + +import com.mojang.brigadier.CommandDispatcher; +import me.lucko.spark.common.sampler.TickCounter; +import me.lucko.spark.fabric.FabricCommandSender; +import me.lucko.spark.fabric.FabricSparkGameHooks; +import me.lucko.spark.fabric.FabricSparkMod; +import me.lucko.spark.fabric.FabricTickCounter; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.server.command.CommandOutput; +import net.minecraft.server.command.CommandSource; + +import java.util.Arrays; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +public class FabricClientSparkPlugin extends FabricSparkPlugin { + + public static void register(FabricSparkMod mod, MinecraftClient client) { + FabricClientSparkPlugin plugin = new FabricClientSparkPlugin(mod, client); + + plugin.scheduler.scheduleWithFixedDelay(plugin::checkCommandRegistered, 10, 10, TimeUnit.SECONDS); + } + + private final MinecraftClient minecraft; + private CommandDispatcher dispatcher; + + public FabricClientSparkPlugin(FabricSparkMod mod, MinecraftClient minecraft) { + super(mod); + this.minecraft = minecraft; + } + + private void checkCommandRegistered() { + ClientPlayerEntity player = this.minecraft.player; + if (player == null) { + return; + } + + ClientPlayNetworkHandler connection = player.networkHandler; + if (connection == null) { + return; + } + + try { + CommandDispatcher dispatcher = connection.getCommandDispatcher(); + if (dispatcher != this.dispatcher) { + this.dispatcher = dispatcher; + registerCommands(this.dispatcher, c -> 0, "sparkc", "sparkclient"); + FabricSparkGameHooks.INSTANCE.setChatSendCallback(this::onClientChat); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public boolean onClientChat(String chat) { + String[] split = chat.split(" "); + if (split.length == 0 || (!split[0].equals("/sparkc") && !split[0].equals("/sparkclient"))) { + return false; + } + + String[] args = Arrays.copyOfRange(split, 1, split.length); + this.platform.executeCommand(new FabricCommandSender(this.minecraft.player, this), args); + this.minecraft.inGameHud.getChatHud().addToMessageHistory(chat); + return true; + } + + @Override + public boolean hasPermission(CommandOutput sender, String permission) { + return true; + } + + @Override + public Stream getSendersWithPermission(String permission) { + return Stream.of(new FabricCommandSender(this.minecraft.player, this)); + } + + @Override + public TickCounter createTickCounter() { + return new FabricTickCounter.Client(); + } + + @Override + public String getCommandName() { + return "sparkc"; + } + +} diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricServerSparkPlugin.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricServerSparkPlugin.java new file mode 100644 index 0000000..9729e55 --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricServerSparkPlugin.java @@ -0,0 +1,95 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) + * 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 . + */ + +package me.lucko.spark.fabric.plugin; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import me.lucko.spark.common.sampler.TickCounter; +import me.lucko.spark.fabric.FabricCommandSender; +import me.lucko.spark.fabric.FabricSparkMod; +import me.lucko.spark.fabric.FabricTickCounter; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.command.CommandOutput; +import net.minecraft.server.command.ServerCommandSource; + +import java.util.Arrays; +import java.util.stream.Stream; + +public class FabricServerSparkPlugin extends FabricSparkPlugin implements Command { + + public static void register(FabricSparkMod mod, MinecraftServer server) { + CommandDispatcher dispatcher = server.getCommandManager().getDispatcher(); + + FabricServerSparkPlugin plugin = new FabricServerSparkPlugin(mod, server); + registerCommands(dispatcher, plugin, "spark"); + } + + private final MinecraftServer server; + + public FabricServerSparkPlugin(FabricSparkMod mod, MinecraftServer server) { + super(mod); + this.server = server; + } + + @Override + public int run(CommandContext context) throws CommandSyntaxException { + String[] split = context.getInput().split(" "); + if (split.length == 0 || !split[0].equals("/spark")) { + return 0; + } + + String[] args = Arrays.copyOfRange(split, 1, split.length); + + this.platform.executeCommand(new FabricCommandSender(context.getSource().getPlayer(), this), args); + return 1; + } + + @Override + public boolean hasPermission(CommandOutput sender, String permission) { + if (sender instanceof PlayerEntity) { + return this.server.getPermissionLevel(((PlayerEntity) sender).getGameProfile()) >= 4; + } else { + return true; + } + } + + @Override + public Stream getSendersWithPermission(String permission) { + return Stream.concat( + this.server.getPlayerManager().getPlayerList().stream() + .filter(player -> hasPermission(player, permission)), + Stream.of(this.server) + ).map(sender -> new FabricCommandSender(sender, this)); + } + + @Override + public TickCounter createTickCounter() { + return new FabricTickCounter.Server(); + } + + @Override + public String getCommandName() { + return "spark"; + } +} diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricSparkPlugin.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricSparkPlugin.java new file mode 100644 index 0000000..6672358 --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/plugin/FabricSparkPlugin.java @@ -0,0 +1,94 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) + * 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 . + */ + +package me.lucko.spark.fabric.plugin; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.tree.LiteralCommandNode; +import me.lucko.spark.common.SparkPlatform; +import me.lucko.spark.common.SparkPlugin; +import me.lucko.spark.common.sampler.ThreadDumper; +import me.lucko.spark.fabric.FabricSparkMod; +import net.minecraft.server.command.CommandOutput; + +import java.nio.file.Path; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + +public abstract class FabricSparkPlugin implements SparkPlugin { + + public static void registerCommands(CommandDispatcher dispatcher, Command executor, String... aliases) { + if (aliases.length == 0) { + return; + } + + String mainName = aliases[0]; + LiteralArgumentBuilder command = LiteralArgumentBuilder.literal(mainName) + .executes(executor) + .then(RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()) + .executes(executor) + ); + + LiteralCommandNode node = dispatcher.register(command); + for (int i = 1; i < aliases.length; i++) { + dispatcher.register(LiteralArgumentBuilder.literal(aliases[i]).redirect(node)); + } + } + + private final FabricSparkMod mod; + protected final ScheduledExecutorService scheduler; + protected final SparkPlatform platform; + + protected FabricSparkPlugin(FabricSparkMod mod) { + this.mod = mod; + this.scheduler = Executors.newSingleThreadScheduledExecutor( + new ThreadFactoryBuilder().setNameFormat("spark-fabric-async-worker").build() + ); + this.platform = new SparkPlatform(this); + this.platform.enable(); + } + + public abstract boolean hasPermission(CommandOutput sender, String permission); + + @Override + public String getVersion() { + return this.mod.getVersion(); + } + + @Override + public Path getPluginDirectory() { + return this.mod.getConfigDirectory(); + } + + @Override + public void executeAsync(Runnable task) { + this.scheduler.execute(task); + } + + @Override + public ThreadDumper getDefaultThreadDumper() { + return new ThreadDumper.Specific(new long[]{Thread.currentThread().getId()}); + } +} diff --git a/spark-fabric/src/main/resources/assets/spark/icon.png b/spark-fabric/src/main/resources/assets/spark/icon.png index fef8f70..bb6bd0e 100644 Binary files a/spark-fabric/src/main/resources/assets/spark/icon.png and b/spark-fabric/src/main/resources/assets/spark/icon.png differ diff --git a/spark-fabric/src/main/resources/fabric.mod.json b/spark-fabric/src/main/resources/fabric.mod.json index 13a352d..7b9b0fc 100644 --- a/spark-fabric/src/main/resources/fabric.mod.json +++ b/spark-fabric/src/main/resources/fabric.mod.json @@ -1,13 +1,13 @@ { "schemaVersion": 1, "id": "spark", + "name": "spark", "version": "${pluginVersion}", - "name": "Spark", - "icon": "assets/spark/icon.png", "description": "${pluginDescription}", "authors": [ - "Lucko" + "Luck", "sk89q" ], + "icon": "assets/spark/icon.png", "contact": { "homepage": "https://sparkprofiler.github.io/", "sources": "https://github.com/lucko/spark", 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 deleted file mode 100644 index 0d38ea2..0000000 --- a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeClientSparkPlugin.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * This file is part of spark. - * - * Copyright (c) lucko (Luck) - * 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 . - */ - -package me.lucko.spark.forge; - -import com.mojang.brigadier.CommandDispatcher; -import me.lucko.spark.common.sampler.TickCounter; -import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.player.ClientPlayerEntity; -import net.minecraft.client.network.play.ClientPlayNetHandler; -import net.minecraft.command.ICommandSource; -import net.minecraft.command.ISuggestionProvider; -import net.minecraftforge.client.event.ClientChatEvent; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; - -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.concurrent.TimeUnit; -import java.util.stream.Stream; - -public class ForgeClientSparkPlugin extends ForgeSparkPlugin { - - private static final Field COMMAND_DISPATCHER_FIELD; - static { - COMMAND_DISPATCHER_FIELD = Arrays.stream(ClientPlayNetHandler.class.getDeclaredFields()) - .filter(f -> f.getType() == CommandDispatcher.class) - .findFirst().orElseThrow(() -> new RuntimeException("No field with CommandDispatcher type")); - COMMAND_DISPATCHER_FIELD.setAccessible(true); - } - - public static void register(ForgeSparkMod mod, FMLClientSetupEvent event) { - Minecraft minecraft = event.getMinecraftSupplier().get(); - - ForgeClientSparkPlugin plugin = new ForgeClientSparkPlugin(mod, minecraft); - MinecraftForge.EVENT_BUS.register(plugin); - - plugin.scheduler.scheduleWithFixedDelay(plugin::checkCommandRegistered, 10, 10, TimeUnit.SECONDS); - } - - private final Minecraft minecraft; - private CommandDispatcher dispatcher; - - public ForgeClientSparkPlugin(ForgeSparkMod mod, Minecraft minecraft) { - super(mod); - this.minecraft = minecraft; - } - - private void checkCommandRegistered() { - ClientPlayerEntity player = this.minecraft.player; - if (player == null) { - return; - } - - ClientPlayNetHandler connection = player.connection; - if (connection == null) { - return; - } - - try { - CommandDispatcher dispatcher = (CommandDispatcher) COMMAND_DISPATCHER_FIELD.get(connection); - if (dispatcher != this.dispatcher) { - this.dispatcher = dispatcher; - registerCommands(this.dispatcher, context -> 1, "sparkc", "sparkclient"); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - @SubscribeEvent - public void onClientChat(ClientChatEvent event) { - String chat = event.getMessage(); - String[] split = chat.split(" "); - if (split.length == 0 || (!split[0].equals("/sparkc") && !split[0].equals("/sparkclient"))) { - return; - } - - String[] args = Arrays.copyOfRange(split, 1, split.length); - this.platform.executeCommand(new ForgeCommandSender(this.minecraft.player, this), args); - this.minecraft.ingameGUI.getChatGUI().addToSentMessages(chat); - event.setCanceled(true); - } - - @Override - boolean hasPermission(ICommandSource sender, String permission) { - return true; - } - - @Override - public Stream getSendersWithPermission(String permission) { - return Stream.of(new ForgeCommandSender(this.minecraft.player, this)); - } - - @Override - public TickCounter createTickCounter() { - return new ForgeTickCounter(TickEvent.Type.CLIENT); - } - - @Override - public String getCommandName() { - return "sparkc"; - } - -} 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 index 418cf2d..ff988f0 100644 --- a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeCommandSender.java +++ b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeCommandSender.java @@ -21,6 +21,7 @@ package me.lucko.spark.forge; import me.lucko.spark.common.CommandSender; +import me.lucko.spark.forge.plugin.ForgeSparkPlugin; import net.kyori.text.Component; import net.kyori.text.serializer.gson.GsonComponentSerializer; import net.minecraft.command.ICommandSource; 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 deleted file mode 100644 index 13ccb59..0000000 --- a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeServerSparkPlugin.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is part of spark. - * - * Copyright (c) lucko (Luck) - * 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 . - */ - -package me.lucko.spark.forge; - -import com.mojang.brigadier.Command; -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import me.lucko.spark.common.sampler.TickCounter; -import net.minecraft.command.CommandSource; -import net.minecraft.command.ICommandSource; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.server.MinecraftServer; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.fml.event.server.FMLServerStartingEvent; -import net.minecraftforge.server.permission.DefaultPermissionLevel; -import net.minecraftforge.server.permission.PermissionAPI; - -import java.util.Arrays; -import java.util.stream.Stream; - -public class ForgeServerSparkPlugin extends ForgeSparkPlugin implements Command { - - public static void register(ForgeSparkMod mod, FMLServerStartingEvent event) { - MinecraftServer server = event.getServer(); - CommandDispatcher dispatcher = event.getCommandDispatcher(); - - ForgeServerSparkPlugin plugin = new ForgeServerSparkPlugin(mod, server); - registerCommands(dispatcher, plugin, "spark"); - PermissionAPI.registerNode("spark", DefaultPermissionLevel.OP, "Access to the spark command"); - } - - private final MinecraftServer server; - - public ForgeServerSparkPlugin(ForgeSparkMod mod, MinecraftServer server) { - super(mod); - this.server = server; - } - - @Override - public int run(CommandContext context) throws CommandSyntaxException { - String[] split = context.getInput().split(" "); - if (split.length == 0 || !split[0].equals("/spark")) { - return 0; - } - - String[] args = Arrays.copyOfRange(split, 1, split.length); - - this.platform.executeCommand(new ForgeCommandSender(context.getSource().asPlayer(), this), args); - return 1; - } - - @Override - boolean hasPermission(ICommandSource sender, String permission) { - if (sender instanceof PlayerEntity) { - return PermissionAPI.hasPermission((PlayerEntity) sender, permission); - } else { - return true; - } - } - - @Override - public Stream getSendersWithPermission(String permission) { - return Stream.concat( - this.server.getPlayerList().getPlayers().stream().filter(player -> PermissionAPI.hasPermission(player, permission)), - Stream.of(this.server) - ).map(sender -> new ForgeCommandSender(sender, this)); - } - - @Override - public TickCounter createTickCounter() { - return new ForgeTickCounter(TickEvent.Type.SERVER); - } - - @Override - public String getCommandName() { - return "spark"; - } -} diff --git a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeSparkMod.java b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeSparkMod.java index f3bf5c3..1f7199d 100644 --- a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeSparkMod.java +++ b/spark-forge/src/main/java/me/lucko/spark/forge/ForgeSparkMod.java @@ -20,6 +20,8 @@ package me.lucko.spark.forge; +import me.lucko.spark.forge.plugin.ForgeClientSparkPlugin; +import me.lucko.spark.forge.plugin.ForgeServerSparkPlugin; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.ModContainer; 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 deleted file mode 100644 index 7141e8d..0000000 --- a/spark-forge/src/main/java/me/lucko/spark/forge/ForgeSparkPlugin.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This file is part of spark. - * - * Copyright (c) lucko (Luck) - * 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 . - */ - -package me.lucko.spark.forge; - -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.mojang.brigadier.Command; -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import me.lucko.spark.common.SparkPlatform; -import me.lucko.spark.common.SparkPlugin; -import me.lucko.spark.common.sampler.ThreadDumper; -import net.minecraft.command.ICommandSource; - -import java.nio.file.Path; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; - -public abstract class ForgeSparkPlugin implements SparkPlugin { - - public static void registerCommands(CommandDispatcher dispatcher, Command executor, String... aliases) { - for (String alias : aliases) { - LiteralArgumentBuilder command = LiteralArgumentBuilder.literal(alias) - .executes(executor) - .then(RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()) - .executes(executor) - ); - - dispatcher.register(command); - } - } - - private final ForgeSparkMod mod; - protected final ScheduledExecutorService scheduler; - protected final SparkPlatform platform; - - protected ForgeSparkPlugin(ForgeSparkMod mod) { - this.mod = mod; - this.scheduler = Executors.newSingleThreadScheduledExecutor( - new ThreadFactoryBuilder().setNameFormat("spark-forge-async-worker").build() - ); - this.platform = new SparkPlatform(this); - this.platform.enable(); - } - - abstract boolean hasPermission(ICommandSource sender, String permission); - - @Override - public String getVersion() { - return this.mod.getVersion(); - } - - @Override - public Path getPluginDirectory() { - return this.mod.getConfigDirectory(); - } - - @Override - public void executeAsync(Runnable task) { - this.scheduler.execute(task); - } - - @Override - public ThreadDumper getDefaultThreadDumper() { - return new ThreadDumper.Specific(new long[]{Thread.currentThread().getId()}); - } -} diff --git a/spark-forge/src/main/java/me/lucko/spark/forge/plugin/ForgeClientSparkPlugin.java b/spark-forge/src/main/java/me/lucko/spark/forge/plugin/ForgeClientSparkPlugin.java new file mode 100644 index 0000000..7de0038 --- /dev/null +++ b/spark-forge/src/main/java/me/lucko/spark/forge/plugin/ForgeClientSparkPlugin.java @@ -0,0 +1,127 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) + * 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 . + */ + +package me.lucko.spark.forge.plugin; + +import com.mojang.brigadier.CommandDispatcher; +import me.lucko.spark.common.sampler.TickCounter; +import me.lucko.spark.forge.ForgeCommandSender; +import me.lucko.spark.forge.ForgeSparkMod; +import me.lucko.spark.forge.ForgeTickCounter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraft.client.network.play.ClientPlayNetHandler; +import net.minecraft.command.ICommandSource; +import net.minecraft.command.ISuggestionProvider; +import net.minecraftforge.client.event.ClientChatEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +public class ForgeClientSparkPlugin extends ForgeSparkPlugin { + + private static final Field COMMAND_DISPATCHER_FIELD; + static { + COMMAND_DISPATCHER_FIELD = Arrays.stream(ClientPlayNetHandler.class.getDeclaredFields()) + .filter(f -> f.getType() == CommandDispatcher.class) + .findFirst().orElseThrow(() -> new RuntimeException("No field with CommandDispatcher type")); + COMMAND_DISPATCHER_FIELD.setAccessible(true); + } + + public static void register(ForgeSparkMod mod, FMLClientSetupEvent event) { + Minecraft minecraft = event.getMinecraftSupplier().get(); + + ForgeClientSparkPlugin plugin = new ForgeClientSparkPlugin(mod, minecraft); + MinecraftForge.EVENT_BUS.register(plugin); + + plugin.scheduler.scheduleWithFixedDelay(plugin::checkCommandRegistered, 10, 10, TimeUnit.SECONDS); + } + + private final Minecraft minecraft; + private CommandDispatcher dispatcher; + + public ForgeClientSparkPlugin(ForgeSparkMod mod, Minecraft minecraft) { + super(mod); + this.minecraft = minecraft; + } + + private void checkCommandRegistered() { + ClientPlayerEntity player = this.minecraft.player; + if (player == null) { + return; + } + + ClientPlayNetHandler connection = player.connection; + if (connection == null) { + return; + } + + try { + CommandDispatcher dispatcher = (CommandDispatcher) COMMAND_DISPATCHER_FIELD.get(connection); + if (dispatcher != this.dispatcher) { + this.dispatcher = dispatcher; + registerCommands(this.dispatcher, context -> 1, "sparkc", "sparkclient"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @SubscribeEvent + public void onClientChat(ClientChatEvent event) { + String chat = event.getMessage(); + String[] split = chat.split(" "); + if (split.length == 0 || (!split[0].equals("/sparkc") && !split[0].equals("/sparkclient"))) { + return; + } + + String[] args = Arrays.copyOfRange(split, 1, split.length); + this.platform.executeCommand(new ForgeCommandSender(this.minecraft.player, this), args); + this.minecraft.ingameGUI.getChatGUI().addToSentMessages(chat); + event.setCanceled(true); + } + + @Override + public boolean hasPermission(ICommandSource sender, String permission) { + return true; + } + + @Override + public Stream getSendersWithPermission(String permission) { + return Stream.of(new ForgeCommandSender(this.minecraft.player, this)); + } + + @Override + public TickCounter createTickCounter() { + return new ForgeTickCounter(TickEvent.Type.CLIENT); + } + + @Override + public String getCommandName() { + return "sparkc"; + } + +} diff --git a/spark-forge/src/main/java/me/lucko/spark/forge/plugin/ForgeServerSparkPlugin.java b/spark-forge/src/main/java/me/lucko/spark/forge/plugin/ForgeServerSparkPlugin.java new file mode 100644 index 0000000..5eb61f8 --- /dev/null +++ b/spark-forge/src/main/java/me/lucko/spark/forge/plugin/ForgeServerSparkPlugin.java @@ -0,0 +1,100 @@ +/* + * This file is part of spark. + * + * Copyright (c) lucko (Luck) + * 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 . + */ + +package me.lucko.spark.forge.plugin; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import me.lucko.spark.common.sampler.TickCounter; +import me.lucko.spark.forge.ForgeCommandSender; +import me.lucko.spark.forge.ForgeSparkMod; +import me.lucko.spark.forge.ForgeTickCounter; +import net.minecraft.command.CommandSource; +import net.minecraft.command.ICommandSource; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.MinecraftServer; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.fml.event.server.FMLServerStartingEvent; +import net.minecraftforge.server.permission.DefaultPermissionLevel; +import net.minecraftforge.server.permission.PermissionAPI; + +import java.util.Arrays; +import java.util.stream.Stream; + +public class ForgeServerSparkPlugin extends ForgeSparkPlugin implements Command { + + public static void register(ForgeSparkMod mod, FMLServerStartingEvent event) { + MinecraftServer server = event.getServer(); + CommandDispatcher dispatcher = event.getCommandDispatcher(); + + ForgeServerSparkPlugin plugin = new ForgeServerSparkPlugin(mod, server); + registerCommands(dispatcher, plugin, "spark"); + PermissionAPI.registerNode("spark", DefaultPermissionLevel.OP, "Access to the spark command"); + } + + private final MinecraftServer server; + + public ForgeServerSparkPlugin(ForgeSparkMod mod, MinecraftServer server) { + super(mod); + this.server = server; + } + + @Override + public int run(CommandContext context) throws CommandSyntaxException { + String[] split = context.getInput().split(" "); + if (split.length == 0 || !split[0].equals("/spark")) { + return 0; + } + + String[] args = Arrays.copyOfRange(split, 1, split.length); + + this.platform.executeCommand(new ForgeCommandSender(context.getSource().asPlayer(), this), args); + return 1; + } + + @Override + public boolean hasPermission(ICommandSource sender, St