generated from shrecknt/sun-addon-template
parent
3ab4c6667a
commit
8993d9c5a8
13 changed files with 186 additions and 109 deletions
10
README.md
10
README.md
|
@ -1,9 +1,5 @@
|
||||||
# Sun Addon Template
|
# Sun LiveOverflow Addon
|
||||||
|
|
||||||
## Setup
|
Utilities for the LiveOverflow CTF server.
|
||||||
|
|
||||||
For setup instructions please see the [fabric wiki page](https://fabricmc.net/wiki/tutorial:setup) that relates to the IDE that you are using.
|
Only works with [Sun Client](https://git.shrecked.dev/Shrecknt/sun).
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This template is available under the CC0 license. Feel free to learn from it and incorporate it in your own projects.
|
|
|
@ -10,8 +10,8 @@ loader_version=0.16.14
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=1.0.0
|
mod_version=1.0.0
|
||||||
maven_group=com.example
|
maven_group=dev.shrecked.ctf
|
||||||
archives_base_name=sun-addon-template
|
archives_base_name=ctf
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
sun_version=1.2.1
|
sun_version=1.2.1
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
package com.example;
|
|
||||||
|
|
||||||
import com.mojang.logging.LogUtils;
|
|
||||||
import dev.shrecked.sun.SunMod;
|
|
||||||
import dev.shrecked.sun.components.SunAddonInitializer;
|
|
||||||
import dev.shrecked.sun.components.command.CommandRegistry;
|
|
||||||
import dev.shrecked.sun.components.module.ModuleRegistry;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
|
|
||||||
public class ExampleAddon implements SunAddonInitializer {
|
|
||||||
public static final Logger LOGGER = LogUtils.getLogger();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInitialize() {
|
|
||||||
SunMod.NORBIT.registerLambdaFactory("com.example", (lookupInMethod, klass) -> (MethodHandles.Lookup) lookupInMethod.invoke(null, klass, MethodHandles.lookup()));
|
|
||||||
LOGGER.info("Sun example addon initialized!");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadModules() {
|
|
||||||
ModuleRegistry.reflectModulesFrom("com.example.modules");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadCommands() {
|
|
||||||
CommandRegistry.reflectCommandsFrom("com.example.commands");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package com.example.commands;
|
|
||||||
|
|
||||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
|
||||||
import dev.shrecked.sun.components.annotation.SunCommand;
|
|
||||||
import dev.shrecked.sun.components.command.Command;
|
|
||||||
import dev.shrecked.sun.util.ChatUtil;
|
|
||||||
import net.minecraft.command.CommandSource;
|
|
||||||
|
|
||||||
@SunCommand(name = "example-command", alias = {"ex"})
|
|
||||||
public class ExampleCommand extends Command {
|
|
||||||
@Override
|
|
||||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
|
||||||
builder.then(literal("echo")
|
|
||||||
.then(argument("text", StringArgumentType.greedyString()).executes(context -> {
|
|
||||||
String text = context.getArgument("text", String.class);
|
|
||||||
ChatUtil.info(String.format("echo! %s", text));
|
|
||||||
return SINGLE_SUCCESS;
|
|
||||||
}))
|
|
||||||
).build();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
package com.example.modules;
|
|
||||||
|
|
||||||
import com.example.ExampleAddon;
|
|
||||||
import dev.shrecked.sun.components.annotation.SunModule;
|
|
||||||
import dev.shrecked.sun.components.event.Events;
|
|
||||||
import dev.shrecked.sun.components.module.Category;
|
|
||||||
import dev.shrecked.sun.components.module.Module;
|
|
||||||
import dev.shrecked.sun.components.setting.settings.StringSetting;
|
|
||||||
import meteordevelopment.orbit.EventHandler;
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
|
|
||||||
@SunModule(key = "example-module", category = Category.World.class)
|
|
||||||
public class ExampleModule extends Module {
|
|
||||||
private final StringSetting text = config.add("text", new StringSetting("Example text display!"));
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onEnable() {
|
|
||||||
ExampleAddon.LOGGER.info("enabled example module!");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDisable() {
|
|
||||||
ExampleAddon.LOGGER.info("disabled example module!");
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
private void onHudRender(Events.HudRender event) {
|
|
||||||
event.context().drawText(
|
|
||||||
MinecraftClient.getInstance().textRenderer,
|
|
||||||
this.text.getValue(),
|
|
||||||
5,
|
|
||||||
5,
|
|
||||||
Color.RED.getRGB(),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
40
src/main/java/dev/shrecked/ctf/CtfAddon.java
Normal file
40
src/main/java/dev/shrecked/ctf/CtfAddon.java
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
package dev.shrecked.ctf;
|
||||||
|
|
||||||
|
import com.mojang.logging.LogUtils;
|
||||||
|
import dev.shrecked.sun.SunMod;
|
||||||
|
import dev.shrecked.sun.components.SunAddonInitializer;
|
||||||
|
import dev.shrecked.sun.components.annotation.SunCategory;
|
||||||
|
import dev.shrecked.sun.components.command.CommandRegistry;
|
||||||
|
import dev.shrecked.sun.components.module.Category;
|
||||||
|
import dev.shrecked.sun.components.module.ModuleRegistry;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
|
||||||
|
public class CtfAddon implements SunAddonInitializer {
|
||||||
|
public static final Logger LOGGER = LogUtils.getLogger();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInitialize() {
|
||||||
|
SunMod.NORBIT.registerLambdaFactory("dev.shrecked.ctf", (lookupInMethod, klass) -> (MethodHandles.Lookup) lookupInMethod.invoke(null, klass, MethodHandles.lookup()));
|
||||||
|
LOGGER.info("Sun example addon initialized!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadCategories() {
|
||||||
|
Category.add(CtfCategory.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadModules() {
|
||||||
|
ModuleRegistry.reflectModulesFrom("dev.shrecked.ctf.modules");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadCommands() {
|
||||||
|
CommandRegistry.reflectCommandsFrom("dev.shrecked.ctf.commands");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SunCategory(key = "ctf")
|
||||||
|
public static class CtfCategory extends Category {}
|
||||||
|
}
|
25
src/main/java/dev/shrecked/ctf/mixin/EventlessMoveMixin.java
Normal file
25
src/main/java/dev/shrecked/ctf/mixin/EventlessMoveMixin.java
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package dev.shrecked.ctf.mixin;
|
||||||
|
|
||||||
|
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||||
|
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||||
|
import dev.shrecked.ctf.modules.RoboWalk;
|
||||||
|
import dev.shrecked.sun.components.module.ModuleRegistry;
|
||||||
|
import dev.shrecked.sun.modules.EventlessMove;
|
||||||
|
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||||
|
import net.minecraft.network.packet.Packet;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
|
||||||
|
@Mixin(EventlessMove.class)
|
||||||
|
public class EventlessMoveMixin {
|
||||||
|
/**
|
||||||
|
* FIXME: The position generated by {@code from.lerp(to, 0.499)} ({@code ordinal = 1}) is rounded, so this movement is too far and generates a movement event.
|
||||||
|
*/
|
||||||
|
@WrapOperation(method = "onPlayerMove", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V", ordinal = 4))
|
||||||
|
private void onPlayerMove(ClientPlayNetworkHandler instance, Packet<?> packet, Operation<Void> original) {
|
||||||
|
RoboWalk roboWalk = ModuleRegistry.fromClass(RoboWalk.class);
|
||||||
|
if (roboWalk.isEnabled()) roboWalk.forceDisableHandler = true;
|
||||||
|
original.call(instance, packet);
|
||||||
|
if (roboWalk.isEnabled()) roboWalk.forceDisableHandler = false;
|
||||||
|
}
|
||||||
|
}
|
41
src/main/java/dev/shrecked/ctf/modules/GameStateSpoofer.java
Normal file
41
src/main/java/dev/shrecked/ctf/modules/GameStateSpoofer.java
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package dev.shrecked.ctf.modules;
|
||||||
|
|
||||||
|
import dev.shrecked.ctf.CtfAddon;
|
||||||
|
import dev.shrecked.sun.components.annotation.SunModule;
|
||||||
|
import dev.shrecked.sun.components.event.Events;
|
||||||
|
import dev.shrecked.sun.components.module.Module;
|
||||||
|
import meteordevelopment.orbit.EventHandler;
|
||||||
|
import net.minecraft.network.packet.s2c.play.GameStateChangeS2CPacket;
|
||||||
|
import net.minecraft.network.packet.s2c.play.WorldBorderInitializeS2CPacket;
|
||||||
|
import net.minecraft.network.packet.s2c.play.WorldBorderSizeChangedS2CPacket;
|
||||||
|
import net.minecraft.world.border.WorldBorder;
|
||||||
|
|
||||||
|
@SunModule(key = "game-state-spoofer", category = CtfAddon.CtfCategory.class)
|
||||||
|
public class GameStateSpoofer extends Module {
|
||||||
|
@EventHandler
|
||||||
|
private void onInboundPacket(Events.InboundPacket event) {
|
||||||
|
if (event.packet instanceof WorldBorderSizeChangedS2CPacket) {
|
||||||
|
event.packet = new WorldBorderSizeChangedS2CPacket(worldBorder());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.packet instanceof WorldBorderInitializeS2CPacket) {
|
||||||
|
event.packet = new WorldBorderInitializeS2CPacket(worldBorder());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.packet instanceof GameStateChangeS2CPacket packet) {
|
||||||
|
GameStateChangeS2CPacket.Reason reason = packet.getReason();
|
||||||
|
if (reason == GameStateChangeS2CPacket.GAME_MODE_CHANGED
|
||||||
|
|| reason == GameStateChangeS2CPacket.GAME_WON
|
||||||
|
|| reason == GameStateChangeS2CPacket.DEMO_MESSAGE_SHOWN) {
|
||||||
|
event.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WorldBorder worldBorder() {
|
||||||
|
WorldBorder worldBorder = new WorldBorder();
|
||||||
|
worldBorder.setCenter(0, 0);
|
||||||
|
worldBorder.setSize(Double.MAX_VALUE);
|
||||||
|
return worldBorder;
|
||||||
|
}
|
||||||
|
}
|
54
src/main/java/dev/shrecked/ctf/modules/RoboWalk.java
Normal file
54
src/main/java/dev/shrecked/ctf/modules/RoboWalk.java
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
package dev.shrecked.ctf.modules;
|
||||||
|
|
||||||
|
import dev.shrecked.ctf.CtfAddon;
|
||||||
|
import dev.shrecked.sun.components.annotation.SunModule;
|
||||||
|
import dev.shrecked.sun.components.event.Events;
|
||||||
|
import dev.shrecked.sun.components.module.Module;
|
||||||
|
import dev.shrecked.sun.util.ChatUtil;
|
||||||
|
import meteordevelopment.orbit.EventHandler;
|
||||||
|
import meteordevelopment.orbit.EventPriority;
|
||||||
|
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
|
||||||
|
import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
@SunModule(key = "robo-walk", category = CtfAddon.CtfCategory.class)
|
||||||
|
public class RoboWalk extends Module {
|
||||||
|
public boolean forceDisableHandler = false;
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
|
private void onOutboundPacket(Events.OutboundPacket event) {
|
||||||
|
if (forceDisableHandler) return;
|
||||||
|
if (event.packet instanceof PlayerMoveC2SPacket packet && packet.changesPosition()) {
|
||||||
|
double newX = round(packet.getX(0f));
|
||||||
|
double newY = packet.getY(0f);
|
||||||
|
double newZ = round(packet.getZ(0f));
|
||||||
|
|
||||||
|
PlayerMoveC2SPacket newPacket;
|
||||||
|
if (packet instanceof PlayerMoveC2SPacket.PositionAndOnGround) {
|
||||||
|
newPacket = new PlayerMoveC2SPacket.PositionAndOnGround(newX, newY, newZ, packet.isOnGround(), packet.horizontalCollision());
|
||||||
|
} else if (packet instanceof PlayerMoveC2SPacket.Full) {
|
||||||
|
newPacket = new PlayerMoveC2SPacket.Full(newX, newY, newZ, packet.getYaw(0f), packet.getPitch(0f), packet.isOnGround(), packet.horizontalCollision());
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Unhandled movement packet type '" + packet.getClass().getSimpleName() + "'");
|
||||||
|
}
|
||||||
|
event.packet = newPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.packet instanceof VehicleMoveC2SPacket(Vec3d position, float yaw, float pitch, boolean onGround)) {
|
||||||
|
Vec3d fixedPosition = new Vec3d(
|
||||||
|
round(position.getX()),
|
||||||
|
position.getY(),
|
||||||
|
round(position.getZ())
|
||||||
|
);
|
||||||
|
event.packet = new VehicleMoveC2SPacket(fixedPosition, yaw, pitch, onGround);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double round(double value) {
|
||||||
|
double rounded = (double) (Math.round(value * 100)) / 100;
|
||||||
|
double res = Math.nextAfter(rounded, rounded + Math.signum(value));
|
||||||
|
long check = ((long) (res * 1000)) % 10;
|
||||||
|
if (check != 0) ChatUtil.error("Bad round " + value);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
Before Width: | Height: | Size: 453 B After Width: | Height: | Size: 453 B |
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
"sun.modules.example-module": "Example Module",
|
"sun.category.ctf": "LiveOverflow CTF",
|
||||||
"sun.modules.example-module.setting.text": "Example Text Config Option"
|
"sun.modules.game-state-spoofer": "Game State Spoof",
|
||||||
|
"sun.modules.robo-walk": "Robo-Walk"
|
||||||
}
|
}
|
8
src/main/resources/ctf.mixins.json
Normal file
8
src/main/resources/ctf.mixins.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"required": true,
|
||||||
|
"package": "dev.shrecked.ctf.mixin",
|
||||||
|
"compatibilityLevel": "JAVA_21",
|
||||||
|
"client": [
|
||||||
|
"EventlessMoveMixin"
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,29 +1,32 @@
|
||||||
{
|
{
|
||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"id": "sun-addon-template",
|
"id": "ctf",
|
||||||
"version": "${version}",
|
"version": "${version}",
|
||||||
"name": "Sun Addon Template",
|
"name": "Sun LiveOverflow Addon",
|
||||||
"description": "A template addon for Sun client",
|
"description": "Sun client addon for the LiveOverflow CTF server",
|
||||||
"authors": [
|
"authors": [
|
||||||
"Me!"
|
"Shrecknt"
|
||||||
],
|
],
|
||||||
"contact": {
|
"contact": {
|
||||||
"homepage": "https://shrecked.dev/",
|
"homepage": "https://shrecked.dev/",
|
||||||
"sources": "https://git.ssi.fyi/Shrecknt/sun-addon-template"
|
"sources": "https://git.ssi.fyi/Shrecknt/sun-addon-template"
|
||||||
},
|
},
|
||||||
"license": "CC0-1.0",
|
"license": "CC0-1.0",
|
||||||
"icon": "assets/sun-addon-template/icon.png",
|
"icon": "assets/ctf/icon.png",
|
||||||
"environment": "*",
|
"environment": "*",
|
||||||
"entrypoints": {
|
"entrypoints": {
|
||||||
"sun-addon": [
|
"sun-addon": [
|
||||||
"com.example.ExampleAddon"
|
"dev.shrecked.ctf.CtfAddon"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"mixins": [
|
||||||
|
"ctf.mixins.json"
|
||||||
|
],
|
||||||
"depends": {
|
"depends": {
|
||||||
"fabricloader": ">=0.15.0",
|
"fabricloader": ">=0.15.0",
|
||||||
"minecraft": ">=1.21.1",
|
"minecraft": ">=1.21.1",
|
||||||
"java": ">=21",
|
"java": ">=21",
|
||||||
"fabric-api": "*",
|
"fabric-api": "*",
|
||||||
"sun": ">=1.1.0"
|
"sun": ">=1.2.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue