diff options
16 files changed, 822 insertions, 0 deletions
diff --git a/build.gradle b/build.gradle index 831ed9b..76bbdca 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,10 @@ allprojects { group = 'me.lucko' version = '1.3-SNAPSHOT' + + configurations { + compileClasspath // Fabric-loom needs this for remap jar for some reason + } } subprojects { diff --git a/settings.gradle b/settings.gradle index 908e607..4457134 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,14 @@ +pluginManagement { + repositories { + jcenter() + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + gradlePluginPortal() + } +} + rootProject.name = 'spark' include ( 'spark-common', @@ -6,5 +17,6 @@ include ( 'spark-velocity', 'spark-sponge', 'spark-forge', + 'spark-fabric', 'spark-universal' ) diff --git a/spark-fabric/build.gradle b/spark-fabric/build.gradle new file mode 100644 index 0000000..ca0ce24 --- /dev/null +++ b/spark-fabric/build.gradle @@ -0,0 +1,55 @@ +plugins { + id 'fabric-loom' version '0.2.5-SNAPSHOT' + id 'com.github.johnrengelman.shadow' version '4.0.1' +} + +configurations { + shade + compile.extendsFrom shade +} + +dependencies { + minecraft "com.mojang:minecraft:19w34a" + mappings "net.fabricmc:yarn:19w34a+build.8" + modCompile "net.fabricmc:fabric-loader:0.4.9+build.161" + + shade project(':spark-common') +} + +processResources { + inputs.property "version", project.version + + from(sourceSets.main.resources.srcDirs) { + include "fabric.mod.json" + expand "pluginVersion": project.pluginVersion, "pluginDescription": project.pluginDescription + } + + from(sourceSets.main.resources.srcDirs) { + exclude "fabric.mod.json" + } +} + +shadowJar { + archiveFileName = 'spark-fabric-dev.jar' + configurations = [project.configurations.shade] + + relocate 'okio', 'me.lucko.spark.lib.okio' + relocate 'okhttp3', 'me.lucko.spark.lib.okhttp3' + relocate 'net.kyori.text', 'me.lucko.spark.lib.text' + relocate 'org.tukaani.xz', 'me.lucko.spark.lib.xz' + relocate 'com.google.protobuf', 'me.lucko.spark.lib.protobuf' +} + +task remappedShadowJar(type: net.fabricmc.loom.task.RemapJarTask) { + dependsOn tasks.shadowJar + input = tasks.shadowJar.archiveFile + addNestedDependencies = true + archiveFileName = 'spark-fabric.jar' +} + +tasks.assemble.dependsOn tasks.remappedShadowJar + +artifacts { + archives remappedShadowJar + shadow shadowJar +} 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 new file mode 100644 index 0000000..1421779 --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricClientSparkPlugin.java @@ -0,0 +1,104 @@ +/* + * 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.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<CommandSource> 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<CommandSource> 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<FabricCommandSender> 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 new file mode 100644 index 0000000..3a8d128 --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricCommandSender.java @@ -0,0 +1,94 @@ +/* + * 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.fabric; + +import me.lucko.spark.common.CommandSender; +import net.kyori.text.Component; +import net.kyori.text.serializer.gson.GsonComponentSerializer; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.command.CommandOutput; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.text.Text; + +import java.util.UUID; + +public class FabricCommandSender implements CommandSender { + + private final VanillaPermission permission; + private final CommandOutput sender; + + public FabricCommandSender(VanillaPermission permission, CommandOutput sender) { + this.permission = permission; + this.sender = sender; + } + + @Override + public String getName() { + if (this.sender instanceof PlayerEntity) { + return ((PlayerEntity) this.sender).getGameProfile().getName(); + } else if (this.sender instanceof DedicatedServer) { + return "Console"; + } else { + return "unknown:" + this.sender.getClass().getSimpleName(); + } + } + + @Override + public UUID getUniqueId() { + if (this.sender instanceof PlayerEntity) { + return ((PlayerEntity) this.sender).getUuid(); + } + return null; + } + + @Override + public void sendMessage(Component message) { + Text component = Text.Serializer.fromJson(GsonComponentSerializer.INSTANCE.serialize(message)); + this.sender.sendMessage(component); + } + + @Override + public boolean hasPermission(String permission) { + return this.permission.hasPermissionLevel(4); // Require /stop access, reasonable + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + FabricCommandSender that = (FabricCommandSender) o; + return this.sender.equals(that.sender); + } + + @Override + 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 new file mode 100644 index 0000000..01bc442 --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricServerSparkPlugin.java @@ -0,0 +1,84 @@ +/* + * 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.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<ServerCommandSource> { + + private final MinecraftServer server; + + public FabricServerSparkPlugin(FabricSparkMod mod, MinecraftServer server) { + super(mod); + this.server = server; + } + + public static void register(FabricSparkMod mod, MinecraftServer server) { + CommandDispatcher<ServerCommandSource> 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<ServerCommandSource> 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<FabricCommandSender> 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/FabricSparkMod.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricSparkMod.java new file mode 100644 index 0000000..4e4468b --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricSparkMod.java @@ -0,0 +1,106 @@ +/* + * 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.fabric; + +import net.fabricmc.api.ModInitializer; +import net.fabricmc.loader.api.FabricLoader; + +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 instance; + private final Set<FabricTickCounter> clientCounters = new HashSet<>(); + private final Set<FabricTickCounter> serverCounters = new HashSet<>(); + private String version; + private Path configDir; + // Use events from Fabric API later + // Return true to abort sending to server + private Predicate<String> chatSendCallback = s -> false; + + public FabricSparkMod() { + } + + public static FabricSparkMod getInstance() { + return instance; + } + + @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"); + + // When Fabric API is available, we will register event listeners here + } + + public String getVersion() { + return version; + } + + public Path getConfigDirectory() { + return configDir; + } + + public void setChatSendCallback(Predicate<String> 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(); + } + } +} 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 new file mode 100644 index 0000000..a0f6cf0 --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricSparkPlugin.java @@ -0,0 +1,89 @@ +/* + * 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.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 <T> void registerCommands(CommandDispatcher<T> dispatcher, Command<T> executor, String... aliases) { + if (aliases.length == 0) { + return; + } + String mainName = aliases[0]; + LiteralArgumentBuilder<T> command = LiteralArgumentBuilder.<T>literal(mainName) + .executes(executor) + .then(RequiredArgumentBuilder.<T, String>argument("args", StringArgumentType.greedyString()) + .executes(executor) + ); + + LiteralCommandNode<T> node = dispatcher.register(command); + for (int i = 1; i < aliases.length; i++) { + dispatcher.register(LiteralArgumentBuilder.<T>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 new file mode 100644 index 0000000..03d00b2 --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/FabricTickCounter.java @@ -0,0 +1,72 @@ +/* + * 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.fabric; + +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 { + + private final Set<TickTask> tasks = new HashSet<>(); + private final Consumer<FabricTickCounter> adder; + private final Consumer<FabricTickCounter> remover; + private int tick = 0; + + public FabricTickCounter(Consumer<FabricTickCounter> adder, Consumer<FabricTickCounter> remover) { + this.adder = adder; + this.remover = remover; + } + + public void onTick() { + for (TickTask r : this.tasks) { + r.onTick(this); + } + 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; + } + + @Override + public void addTickTask(TickTask runnable) { + this.tasks.add(runnable); + } + + @Override + public void removeTickTask(TickTask runnable) { + this.tasks.remove(runnable); + } +} 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 new file mode 100644 index 0000000..3ce57b1 --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/ClientPlayerEntityMixin.java @@ -0,0 +1,49 @@ +/* + * 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.fabric.mixin; + +import com.mojang.authlib.GameProfile; +import me.lucko.spark.fabric.FabricSparkMod; +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.world.ClientWorld; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +@Mixin(ClientPlayerEntity.class) +public abstract class ClientPlayerEntityMixin extends AbstractClientPlayerEntity { + + public ClientPlayerEntityMixin(ClientWorld clientWorld_1, GameProfile gameProfile_1) { + super(clientWorld_1, gameProfile_1); + } + + @Inject(method = "sendChatMessage(Ljava/lang/String;)V", at = @At("HEAD"), + locals = LocalCapture.CAPTURE_FAILHARD, + cancellable = true) + public void onSendChatMessage(String message, CallbackInfo ci) { + if (FabricSparkMod.getInstance().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 new file mode 100644 index 0000000..b987ca6 --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/MinecraftClientMixin.java @@ -0,0 +1,51 @@ +/* + * 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.fabric.mixin; + +import me.lucko.spark.fabric.FabricClientSparkPlugin; +import me.lucko.spark.fabric.FabricSparkMod; +import net.minecraft.client.MinecraftClient; +import net.minecraft.util.NonBlockingThreadExecutor; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftClient.class) +public abstract class MinecraftClientMixin extends NonBlockingThreadExecutor<Runnable> { + + public MinecraftClientMixin(String string_1) { + super(string_1); + } + + // Inject at when menu pops up + @Inject(method = "init()V", at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/gui/screen/SplashScreen;method_18819(Lnet/minecraft/client/MinecraftClient;)V")) + public void onInit(CallbackInfo ci) { + FabricClientSparkPlugin.register(FabricSparkMod.getInstance(), (MinecraftClient) (Object) this); + } + + @Inject(method = "tick()V", at = @At("RETURN")) + public void onTick(CallbackInfo ci) { + FabricSparkMod.getInstance().tickClientCounters(); + } + +} diff --git a/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/MinecraftServerMixin.java b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/MinecraftServerMixin.java new file mode 100644 index 0000000..bb14b64 --- /dev/null +++ b/spark-fabric/src/main/java/me/lucko/spark/fabric/mixin/MinecraftServerMixin.java @@ -0,0 +1,52 @@ +/* + * 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.fabric.mixin; + +import me.lucko.spark.fabric.FabricServerSparkPlugin; +import me.lucko.spark.fabric.FabricSparkMod; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.ServerTask; +import net.minecraft.util.NonBlockingThreadExecutor; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftServer.class) +public abstract class MinecraftServerMixin extends NonBlockingThreadExecutor<ServerTask> { + + public MinecraftServerMixin(String string_1) { + super(string_1); + } + + // Inject before set favicon call + @Inject(method = "run()V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;setFavicon(Lnet/minecraft/server/ServerMetadata;)V")) + public void onRun(CallbackInfo ci) { + FabricServerSparkPlugin.register(FabricSparkMod.getInstance(), (MinecraftServer) (Object) this); + } + + @Inject(method = "tick(Ljava/util/function/BooleanSupplier;)V", at = @At("RETURN")) + public void onTick(CallbackInfo ci) { + FabricSparkMod.getInstance().tickServerCounters(); + } + +} diff --git a/spark-fabric/src/main/resources/assets/spark/icon.png b/spark-fabric/src/main/resources/assets/spark/icon.png Binary files differnew file mode 100644 index 0000000..fef8f70 --- /dev/null +++ b/spark-fabric/src/main/resources/assets/spark/icon.png diff --git a/spark-fabric/src/main/resources/fabric.mod.json b/spark-fabric/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..13a352d --- /dev/null +++ b/spark-fabric/src/main/resources/fabric.mod.json @@ -0,0 +1,29 @@ +{ + "schemaVersion": 1, + "id": "spark", + "version": "${pluginVersion}", + "name": "Spark", + "icon": "assets/spark/icon.png", + "description": "${pluginDescription}", + "authors": [ + "Lucko" + ], + "contact": { + "homepage": "https://sparkprofiler.github.io/", + "sources": "https://github.com/lucko/spark", + "issues": "https://github.com/lucko/spark/issues" + }, + "license": "GNU General Public License v3.0", + "environment": "*", + "entrypoints": { + "main": [ + "me.lucko.spark.fabric.FabricSparkMod" + ] + }, + "mixins": [ + "spark.mixins.json" + ], + "depends": { + "fabricloader": ">=0.4.0" + } +} diff --git a/spark-fabric/src/main/resources/pack.mcmeta b/spark-fabric/src/main/resources/pack.mcmeta new file mode 100644 index 0000000..e6c4c25 --- /dev/null +++ b/spark-fabric/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "spark resources", + "pack_format": 4 + } +} diff --git a/spark-fabric/src/main/resources/spark.mixins.json b/spark-fabric/src/main/resources/spark.mixins.json new file mode 100644 index 0000000..bde03fb --- /dev/null +++ b/spark-fabric/src/main/resources/spark.mixins.json @@ -0,0 +1,15 @@ +{ + "required": true, + "package": "me.lucko.spark.fabric.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "MinecraftServerMixin" + ], + "client": [ + "MinecraftClientMixin", + "ClientPlayerEntityMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} |