Compare commits

...
4 Commits
Author SHA1 Message Date
retuci0 86594f1ca3 v2.9 2026-01-18 22:53:21 +01:00
retuci0 f074f05c51 v2.8 2026-01-17 17:12:54 +01:00
retuci0 436b79fd2b v2.7 2026-01-17 00:33:24 +01:00
retuci0 9afaa4e0c8 v2.6 2026-01-11 11:12:44 +01:00
162 changed files with 4151 additions and 982 deletions

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
# jenny's mod 2 100% real
mod para Minecraft Fabric 1.21.10 que añade algunas cosas QOL, mayormente relacionadas a la cámara.
mod para Minecraft Fabric 1.21.11 que añade algunas cosas QOL, mayormente relacionadas a la cámara.
## instalación
+14 -24
View File
@@ -1,6 +1,6 @@
plugins {
id 'fabric-loom' version "${loom_version}"
id 'maven-publish'
id 'fabric-loom' version "${loom_version}"
id 'maven-publish'
}
version = project.mod_version
@@ -11,21 +11,21 @@ base {
}
repositories {
// Add repositories to retrieve artifacts from in here.
// You should only use this when depending on other mods because
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.
maven {
name = "FDD Maven"
url = "https://maven.firstdark.dev/releases"
}
}
dependencies {
// To change the versions see the gradle.properties file
// mc
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}"
// otros
include(modImplementation "dev.firstdark.discordrpc:discord-rpc:1.0.3")
}
loom {
@@ -45,11 +45,6 @@ tasks.withType(JavaCompile).configureEach {
}
java {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
withSourcesJar()
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
@@ -58,11 +53,12 @@ jar {
inputs.property "archivesName", project.base.archivesName
from("LICENSE") {
rename { "${it}_${inputs.properties.archivesName}"}
rename {
"${it}_${inputs.properties.archivesName}"
}
}
}
// configure the maven publication
publishing {
publications {
create("mavenJava", MavenPublication) {
@@ -71,11 +67,5 @@ publishing {
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
// Notice: This block does NOT have the same function as the block in the top level.
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
}
repositories {}
}
+17 -2
View File
@@ -1,15 +1,30 @@
# v2.5
# v2.9
## novedades
- grupos de ajustes, para mayor orden, y arreglo de algún que otro bug
varios módulos que no quería añadir porque son cheats en toda regla, pero ya total, como la mayoría que he añadido hasta la fecha es baneable
### adiciones
- categoría de movimiento
#### módulos nuevos:
- packetmine: mina usando paquetes, para minar más rápido o para evitar la animación de minado
- aliviar cpu: evita renderizar objetos en pantalla si la ventana no está seleccionada
- delfín: *ruidos de delfín*
- patinaje: esparce semen allá por donde pisas (haciéndolo más resbaladizo)
- jesús: hermano se cree Jesús (camina sobre el agua)
- info. de bloque: (muestra el contenido nbt de un bloque)
- estampaescrotos: mazo en esteroides
- tenedor mágico: hermano se cree Poseidón (tweaks a la propulsión acuática del tridente)
- elytras: vuela con las elytras (en vez de solo planear)
- barco volador: convierte tu bote de acacia en un caza militar
### arreglos / mejoras
- ahora puedes cambiar el título de la ventana en los ajustes del mod
## problemas reconocidos
- muchos, pero repórtalos en la página de problemas si quieres para que queden bien registrados
+1 -1
View File
@@ -8,6 +8,6 @@ loom_version=1.13-SNAPSHOT
fabric_api_version=0.140.2+1.21.11
mod_version=2.5
mod_version=2.9
maven_group=me.retucio
archives_base_name=sputnik
+14 -1
View File
@@ -19,6 +19,7 @@ import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.client.HUD;
import me.retucio.sputnik.ui.hud.HudRenderer;
import me.retucio.sputnik.ui.screen.ClickGUI;
import me.retucio.sputnik.ui.hud.HudEditorScreen;
import me.retucio.sputnik.ui.widgets.buttons.settings.BindButton;
@@ -29,9 +30,11 @@ import me.retucio.sputnik.ui.widgets.frames.SettingsFrame;
import me.retucio.sputnik.ui.widgets.Button;
import me.retucio.sputnik.util.*;
import me.retucio.sputnik.util.KeyUtil;
import me.retucio.sputnik.util.render.DrawUtil;
import me.retucio.sputnik.util.render.RenderUtil;
import me.retucio.sputnik.util.render.Textures;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.loader.api.FabricLoader;
@@ -69,6 +72,11 @@ public class Sputnik implements ClientModInitializer {
private Screen prevScreen;
public static boolean settingsApplied = false;
static {
// puta vida
System.setProperty("java.awt.headless", "false");
}
@Override
public void onInitializeClient() {
mc = MinecraftClient.getInstance();
@@ -86,6 +94,8 @@ public class Sputnik implements ClientModInitializer {
Lists.init();
Textures.registerAll();
CapeManager.INSTANCE = new CapeManager();
EVENT_BUS.post(new LoadCapeManagerEvent());
@@ -99,6 +109,8 @@ public class Sputnik implements ClientModInitializer {
HudEditorScreen.INSTANCE = new HudEditorScreen();
EVENT_BUS.post(new LoadClickGUIEvent());
mc.execute(HudRenderer::init);
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
EVENT_BUS.post(new ShutdownEvent());
}));
@@ -114,6 +126,7 @@ public class Sputnik implements ClientModInitializer {
}
ModuleManager.INSTANCE.getEnabledModules().forEach(Module::onTick);
mc.getWindow().setTitle(ClientSettingsFrame.guiSettings.windowTitle.getValue());
}
@@ -189,7 +202,7 @@ public class Sputnik implements ClientModInitializer {
// manejar la lógica de apertura del editor de elementos del hud, con la misma lógica que handleClickGUIKey()
private void handleHudEditorKey(int key, boolean anyFocused) {
HUD hud = ModuleManager.INSTANCE.getModuleByClass(HUD.class);
if (key != hud.editorKey.getKey() || anyFocused || isOnTypingScreen()) return;
if (key != hud.editorKey.getValue() || anyFocused || isOnTypingScreen()) return;
if (mc.currentScreen != HudEditorScreen.INSTANCE) {
if (!hud.isEnabled()) {
@@ -32,6 +32,7 @@ public class CommandManager {
public static void registerCommands() {
addCommand(new BindCommand());
addCommand(new ConfigCommand());
addCommand(new CopyScreenshotCommand());
addCommand(new EnderChestCommand());
addCommand(new GarbageCleanerCommand());
@@ -9,6 +9,7 @@ import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.util.MiscUtil;
import net.minecraft.command.CommandSource;
import net.minecraft.text.Text;
@@ -19,6 +20,7 @@ import java.util.concurrent.CompletableFuture;
public class ModuleArgumentType implements ArgumentType<Module> {
public static final ModuleArgumentType INSTANCE = new ModuleArgumentType();
private static final DynamicCommandExceptionType UNKNOWN_MODULE = new DynamicCommandExceptionType(
name -> Text.literal("módulo \"" + name + "\" no encontrado"));
@@ -35,7 +37,8 @@ public class ModuleArgumentType implements ArgumentType<Module> {
@Override
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
return CommandSource.suggestMatching(ModuleManager.INSTANCE.getModules().stream().map(module -> module.getName().replace(" ", "_")), builder);
return CommandSource.suggestMatching(ModuleManager.INSTANCE.getModules()
.stream().map(module -> MiscUtil.removeAccentMarks(module.getName().replace(" ", "_"))), builder);
}
@Override
@@ -42,7 +42,7 @@ public class BindCommand extends Command {
public static boolean onKeyPress(int key) {
if (listeningModule == null) return false;
KeySetting bind = listeningModule.getBind();
if (bind != null) bind.setKey(key);
if (bind != null) bind.setValue(key);
ChatUtil.info(
Text.of("la tecla " + Formatting.AQUA + KeyUtil.getKeyName(key) + Formatting.RESET +
@@ -0,0 +1,66 @@
package me.retucio.sputnik.command.commands;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import me.retucio.sputnik.command.Command;
import me.retucio.sputnik.command.args.ModuleArgumentType;
import me.retucio.sputnik.ui.screen.ClickGUI;
import me.retucio.sputnik.ui.widgets.frames.SettingsFrame;
import net.minecraft.command.CommandSource;
import me.retucio.sputnik.module.Module;
public class ConfigCommand extends Command {
public ConfigCommand() {
super("config", "abre el marco de ajustes de un módulo", "ajustes", "settings");
}
@Override
public void build(LiteralArgumentBuilder<CommandSource> builder) {
builder
.then(argument("módulo", ModuleArgumentType.INSTANCE)
.executes(ctx -> {
mc.execute(() -> openSf(ctx));
return SUCCESS;
})
.then(argument("x", IntegerArgumentType.integer())
.then(argument("y", IntegerArgumentType.integer())
.executes(ctx -> {
mc.execute(() -> openSfWithPos(ctx,
ctx.getArgument("x", Integer.class),
ctx.getArgument("y", Integer.class)));
return SUCCESS;
})
)
)
);
}
private void openSf(CommandContext<CommandSource> ctx) {
Module module = ctx.getArgument("módulo", Module.class);
mc.setScreen(ClickGUI.INSTANCE);
if (ClickGUI.INSTANCE.isSettingsFrameOpen(module)) return;
SettingsFrame sf = ClickGUI.INSTANCE.getSfOfModule(module);
int x = mc.getWindow().getScaledWidth() / 2 - sf.getW() / 2;
int y = 67;
ClickGUI.INSTANCE.openSettingsFrame(module, x, y);
}
private void openSfWithPos(CommandContext<CommandSource> ctx, int x, int y) {
Module module = ctx.getArgument("módulo", Module.class);
mc.setScreen(ClickGUI.INSTANCE);
if (ClickGUI.INSTANCE.isSettingsFrameOpen(module)) {
SettingsFrame sf = ClickGUI.INSTANCE.getSfOfModule(module);
sf.setX(x);
sf.setY(y);
}
ClickGUI.INSTANCE.openSettingsFrame(module, x, y);
}
}
@@ -57,9 +57,9 @@ public class ClientConfig {
// guardar ajustes con su respectivo tipo de valor, en formato "nombreMódulo:nombreAjuste"
Object value = null;
switch (event.getSetting()) {
case BooleanSetting b: value = b.isEnabled(); break;
case BooleanSetting b: value = b.getValue(); break;
case EnumSetting e: value = e.getIndex(); break;
case KeySetting k: value = k.getKey(); break;
case KeySetting k: value = k.getValue(); break;
case NumberSetting n: value = n.getValue(); break;
case StringSetting s: value = s.getValue(); break;
case ListSetting l: value = l.getConfigValues(); break;
@@ -107,7 +107,7 @@ public class ConfigManager {
save();
}
public static void setSetting(Setting setting, Object value) {
public static void setSetting(Setting<?> setting, Object value) {
ensureConfig();
config.settings.put(getSettingKey(setting), value);
save();
@@ -150,7 +150,7 @@ public class ConfigManager {
// ------------------ APLICAR AJUSTES ------------------
@SuppressWarnings({"rawtypes", "unchecked"})
public static void applySetting(Module parent, Setting setting) {
public static void applySetting(Module parent, Setting<?> setting) {
String key = getSettingKey(setting);
if (!config.settings.containsKey(key)) return;
@@ -189,8 +189,15 @@ public class ConfigManager {
private static void applySettingsFrames() {
config.settingsFrames.forEach((moduleName, position) -> {
Module module = ModuleManager.INSTANCE.getModuleByName(moduleName);
if (module == null) {
Sputnik.LOGGER.warn("\"null\" como módulo (\"{}\")", moduleName);
return;
}
ClickGUI.INSTANCE.openSettingsFrame(module, position[0], position[1]);
});
Sputnik.LOGGER.info("estados de marcos de ajustes aplicados");
}
@@ -242,7 +249,7 @@ public class ConfigManager {
private static void applyBooleanSetting(BooleanSetting setting, Object value) {
if (value instanceof Boolean) {
setting.setEnabled((Boolean) value);
setting.setValue((Boolean) value);
}
}
@@ -268,9 +275,9 @@ public class ConfigManager {
private static void applyKeySetting(KeySetting setting, Object value) {
if (value instanceof Double) {
setting.setKey(((Double) value).intValue());
setting.setValue(((Double) value).intValue());
} else if (value instanceof Integer) {
setting.setKey((Integer) value);
setting.setValue((Integer) value);
}
}
@@ -284,7 +291,7 @@ public class ConfigManager {
convertedValues.put(option, booleanValue instanceof Boolean && (Boolean) booleanValue);
}
setting.setValues(convertedValues);
setting.setValue(convertedValues);
}
}
@@ -335,7 +342,7 @@ public class ConfigManager {
if (config == null) config = new ClientConfig();
}
private static String getSettingKey(Setting setting) {
private static String getSettingKey(Setting<?> setting) {
return setting.getSg().getModule().getName() + ":" + setting.getName();
}
@@ -0,0 +1,27 @@
package me.retucio.sputnik.event;
import net.minecraft.entity.vehicle.AbstractBoatEntity;
import net.minecraft.util.math.Vec3d;
public class BoatMoveEvent extends Event {
private final AbstractBoatEntity boat;
private Vec3d pos;
public BoatMoveEvent(AbstractBoatEntity boat, Vec3d pos) {
this.boat = boat;
this.pos = pos;
}
public AbstractBoatEntity getBoat() {
return boat;
}
public Vec3d getPos() {
return pos;
}
public void setPos(Vec3d pos) {
this.pos = pos;
}
}
@@ -0,0 +1,24 @@
package me.retucio.sputnik.event.events;
import me.retucio.sputnik.event.Event;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
public class AttackBlockEvent extends Event {
private final BlockPos pos;
private final Direction dir;
public AttackBlockEvent(BlockPos pos, Direction dir) {
this.pos = pos;
this.dir = dir;
}
public BlockPos getPos() {
return pos;
}
public Direction getDir() {
return dir;
}
}
@@ -0,0 +1,43 @@
package me.retucio.sputnik.event.events;
import me.retucio.sputnik.event.Event;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShape;
public class BlockShapeEvent extends Event {
private BlockState state;
private BlockPos pos;
private VoxelShape shape;
public BlockShapeEvent(BlockState state, BlockPos pos, VoxelShape shape) {
this.state = state;
this.pos = pos;
this.setShape(shape);
}
public BlockState getState() {
return state;
}
public void setState(BlockState state) {
this.state = state;
}
public BlockPos getPos() {
return pos;
}
public void setPos(BlockPos pos) {
this.pos = pos;
}
public VoxelShape getShape() {
return shape;
}
public void setShape(VoxelShape shape) {
this.shape = shape;
}
}
@@ -6,15 +6,15 @@ import me.retucio.sputnik.module.setting.Setting;
// se genera cada que se cambia el valor de un ajuste
public class UpdateSettingEvent extends Event {
private final Setting setting;
private final Setting<?> setting;
private boolean shouldSave;
public UpdateSettingEvent(Setting setting, boolean shouldSave) {
public UpdateSettingEvent(Setting<?> setting, boolean shouldSave) {
this.setting = setting;
this.shouldSave = shouldSave;
}
public Setting getSetting() {
public Setting<?> getSetting() {
return setting;
}
@@ -0,0 +1,31 @@
package me.retucio.sputnik.mixin;
import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.event.BoatMoveEvent;
import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.movement.BoatFly;
import net.minecraft.entity.MovementType;
import net.minecraft.entity.vehicle.AbstractBoatEntity;
import net.minecraft.util.math.Vec3d;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(AbstractBoatEntity.class)
public abstract class AbstractBoatEntityMixin {
@Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/vehicle/AbstractBoatEntity;move(Lnet/minecraft/entity/MovementType;Lnet/minecraft/util/math/Vec3d;)V"))
private void onMove(AbstractBoatEntity instance, MovementType movementType, Vec3d vec3d) {
BoatMoveEvent event = Sputnik.EVENT_BUS.post(new BoatMoveEvent(instance, vec3d));
if(!event.isCancelled()) instance.move(movementType, event.getPos());
}
@Inject(method = "updatePaddles", at = @At("HEAD"), cancellable = true)
private void onPaddle(CallbackInfo ci) {
if (ModuleManager.INSTANCE.getModuleByClass(BoatFly.class).isEnabled()) {
ci.cancel();
}
}
}
@@ -0,0 +1,33 @@
package me.retucio.sputnik.mixin;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.event.events.BlockShapeEvent;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockCollisionSpliterator;
import net.minecraft.world.CollisionView;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import static me.retucio.sputnik.Sputnik.mc;
@Mixin(BlockCollisionSpliterator.class)
public abstract class BlockCollisionSpliteratorMixin {
@WrapOperation(method = "computeNext", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/ShapeContext;getCollisionShape(Lnet/minecraft/block/BlockState;Lnet/minecraft/world/CollisionView;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/util/shape/VoxelShape;"))
private VoxelShape onGetBlockShape(ShapeContext instance, BlockState state, CollisionView collisionView, BlockPos pos, Operation<VoxelShape> original) {
VoxelShape shape = original.call(instance, state, collisionView, pos);
if (collisionView != mc.world) {
return shape;
}
BlockShapeEvent event = Sputnik.EVENT_BUS.post(new BlockShapeEvent(state, pos, shape));
return event.isCancelled() ? VoxelShapes.empty() : event.getShape();
}
}
@@ -15,7 +15,8 @@ import java.util.Iterator;
import static me.retucio.sputnik.Sputnik.EVENT_BUS;
@Mixin(BossBarHud.class)
@Mixin(value = BossBarHud.class)
public abstract class BossBarHudMixin {
@ModifyExpressionValue(method = "render", at = @At(value = "INVOKE", target = "Ljava/util/Collection;iterator()Ljava/util/Iterator;"))
@@ -30,7 +31,8 @@ public abstract class BossBarHudMixin {
return event.getName();
}
@ModifyConstant(method = "render", constant = @Constant(intValue = 9, ordinal = 1))
// require = 0 para meteor
@ModifyConstant(method = "render", constant = @Constant(intValue = 9, ordinal = 1), require = 0)
public int modifySpacingConstant(int constant) {
RenderBossbarEvent.BossSpacing event = EVENT_BUS.post(new RenderBossbarEvent.BossSpacing(constant));
return event.getSpacing();
@@ -59,7 +59,7 @@ public abstract class CameraMixin {
@Inject(method = "clipToSpace", at = @At("HEAD"), cancellable = true)
private void onClipToSpace(float distance, CallbackInfoReturnable<Float> cir) {
if (perspectivePlus.isEnabled() && perspectivePlus.clip.isEnabled())
if (perspectivePlus.isEnabled() && perspectivePlus.clip.getValue())
cir.setReturnValue(distance);
}
@@ -143,7 +143,7 @@ public abstract class ChatHudMixin implements IChatHud {
@ModifyExpressionValue(method = "render(Lnet/minecraft/client/gui/hud/ChatHud$Backend;IIZ)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;ceil(F)I"))
private int onRender_modifyWidth(int width) {
return (chatPlus.isEnabled() && chatPlus.showHeads.isEnabled()) ? width + 10 : width;
return (chatPlus.isEnabled() && chatPlus.showHeads.getValue()) ? width + 10 : width;
}
@@ -19,6 +19,6 @@ public abstract class ChatScreenMixin {
@Inject(method = "init", at = @At(value = "RETURN"))
private void onInit(CallbackInfo info) {
ChatPlus chatPlus = ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class);
if (chatPlus.isEnabled() && chatPlus.noCharLimit.isEnabled()) chatField.setMaxLength(Integer.MAX_VALUE);
if (chatPlus.isEnabled() && chatPlus.noCharLimit.getValue()) chatField.setMaxLength(Integer.MAX_VALUE);
}
}
@@ -55,7 +55,7 @@ public abstract class ClientPlayNetworkHandlerMixin {
@Redirect(method = "onEntityStatus", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;showFloatingItem(Lnet/minecraft/item/ItemStack;)V"))
private void noRenderTotemPop(GameRenderer instance, ItemStack floatingItem) {
NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
if (!noRender.isEnabled() || noRender.totemPop.isEnabled())
if (!noRender.isEnabled() || noRender.totemPop.getValue())
mc.gameRenderer.showFloatingItem(floatingItem);
}
}
@@ -1,11 +1,10 @@
package me.retucio.sputnik.mixin;
import me.retucio.sputnik.event.events.AttackEntityEvent;
import me.retucio.sputnik.event.events.BreakBlockEvent;
import me.retucio.sputnik.event.events.InteractEntityEvent;
import me.retucio.sputnik.event.events.PlaceBlockEvent;
import me.retucio.sputnik.event.events.*;
import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.camera.Freecam;
import me.retucio.sputnik.module.modules.player.FastUse;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
@@ -16,7 +15,8 @@ import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Final;
import net.minecraft.util.math.Direction;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
@@ -28,21 +28,25 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import static me.retucio.sputnik.Sputnik.EVENT_BUS;
import static me.retucio.sputnik.Sputnik.mc;
@Mixin(ClientPlayerInteractionManager.class)
public abstract class ClientPlayerInteractionManagerMixin {
@Shadow @Final
private MinecraftClient client;
@Shadow
private int blockBreakingCooldown;
@Unique
Freecam freecam;
@Unique
FastUse fastUse;
@Inject(method = "<init>", at = @At("TAIL"))
private void getModules(MinecraftClient client, ClientPlayNetworkHandler networkHandler, CallbackInfo ci) {
freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
fastUse = ModuleManager.INSTANCE.getModuleByClass(FastUse.class);
}
@Inject(method = "breakBlock", at = @At("HEAD"), cancellable = true)
private void onBlockBreak(BlockPos pos, CallbackInfoReturnable<Boolean> cir) {
BreakBlockEvent event = EVENT_BUS.post(new BreakBlockEvent(pos));
@@ -56,6 +60,12 @@ public abstract class ClientPlayerInteractionManagerMixin {
if (event.isCancelled()) cir.cancel();
}
@Inject(method = "attackBlock", at = @At("HEAD"), cancellable = true)
private void onAttackBlock(BlockPos pos, Direction direction, CallbackInfoReturnable<Boolean> cir) {
AttackBlockEvent event = EVENT_BUS.post(new AttackBlockEvent(pos, direction));
if (event.isCancelled()) cir.cancel();
}
@Inject(method = "interactEntity", at = @At("HEAD"), cancellable = true)
private void onEntityInteract(PlayerEntity player, Entity entity, Hand hand, CallbackInfoReturnable<ActionResult> cir) {
if (mc.player != player) return;
@@ -69,4 +79,11 @@ public abstract class ClientPlayerInteractionManagerMixin {
AttackEntityEvent event = EVENT_BUS.post(new AttackEntityEvent(target));
if (event.isCancelled()) ci.cancel();
}
@Inject(method = "updateBlockBreakingProgress", at = @At("HEAD"))
private void modifyBlockBreakingCooldown(BlockPos pos, Direction direction, CallbackInfoReturnable<Boolean> cir) {
if (!fastUse.isEnabled() || !fastUse.mining.getValue()) return;
blockBreakingCooldown = fastUse.miningCooldown.getIntValue();
}
}
@@ -41,7 +41,7 @@ abstract class DamageParticleFactoryMixin {
original.velocityMultiplier *= crits.velocityMultipler.getFloatValue();
original.gravityStrength *= crits.gravity.getFloatValue();
original.setMaxAge(crits.maxAge.getIntValue());
original.collidesWithWorld = crits.collide.isEnabled();
original.collidesWithWorld = crits.collide.getValue();
return original;
}
@@ -7,19 +7,23 @@ import me.retucio.sputnik.module.modules.camera.Freecam;
import me.retucio.sputnik.module.modules.camera.Freelook;
import me.retucio.sputnik.module.modules.camera.Rotations;
import me.retucio.sputnik.module.modules.misc.AntiInvis;
import me.retucio.sputnik.module.modules.movement.BoatFly;
import me.retucio.sputnik.module.modules.render.Nametags;
import net.minecraft.entity.*;
import net.minecraft.entity.passive.TameableEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.entity.vehicle.AbstractBoatEntity;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@@ -88,7 +92,7 @@ public abstract class EntityMixin {
@ModifyReturnValue(method = "getName", at = @At("RETURN"))
private Text showProjectileDamage(Text original) {
if (!nametags.isEnabled() || !nametags.showProjectileDamage.isEnabled()) return original;
if (!nametags.isEnabled() || !nametags.showProjectileDamage.getValue()) return original;
if ((Object) this instanceof PersistentProjectileEntity arrow) { // aunque lo llame "arrow", también cubre flechas espectrales y tridentes
String damage = nametags.getArrowDamage(arrow);
@@ -101,7 +105,7 @@ public abstract class EntityMixin {
@SuppressWarnings("ConstantConditions")
@ModifyReturnValue(method = "getCustomName", at = @At("RETURN"))
private Text displayEntityOwner(Text original) {
if (!nametags.isEnabled() || !nametags.petOwner.isEnabled()) return original;
if (!nametags.isEnabled() || !nametags.petOwner.getValue()) return original;
if ((Object) this instanceof TameableEntity entity && entity.getOwnerReference() != null) {
if (original != null) return original.copy().append(" (de " + nametags.getOwnerName(entity.getOwnerReference()) + ")");
else return Text.of(nametags.getOwnerName(entity.getOwnerReference()));
@@ -113,7 +117,7 @@ public abstract class EntityMixin {
@SuppressWarnings("ConstantConditions")
@ModifyReturnValue(method = "getName", at = @At("RETURN"))
private Text showBabies(Text original) {
if (!nametags.isEnabled() || !nametags.distinguishBabies.isEnabled()) return original;
if (!nametags.isEnabled() || !nametags.distinguishBabies.getValue()) return original;
if ((Object) this instanceof LivingEntity entity && entity.isBaby()) return original.copy().append(" (baby)");
return original;
}
@@ -146,7 +150,16 @@ public abstract class EntityMixin {
// otros
@Inject(method = "isInvisibleTo", at = @At("RETURN"), cancellable = true)
public void renderInvisPlayers(PlayerEntity player, CallbackInfoReturnable<Boolean> cir) {
private void renderInvisPlayers(PlayerEntity player, CallbackInfoReturnable<Boolean> cir) {
if (ModuleManager.INSTANCE.getModuleByClass(AntiInvis.class).isEnabled()) cir.setReturnValue(false);
}
@SuppressWarnings("ConstantConditions")
@Inject(method = "getStepHeight", at = @At("RETURN"), cancellable = true)
private void modifyBoatStepHeight(CallbackInfoReturnable<Float> cir) {
BoatFly boatFly = ModuleManager.INSTANCE.getModuleByClass(BoatFly.class);
if (((Object) this) instanceof AbstractBoatEntity && boatFly.isEnabled()) {
cir.setReturnValue(boatFly.stepHeight.getFloatValue());
}
}
}
@@ -33,10 +33,10 @@ public abstract class FogRendererMixin {
if (!noRender.isEnabled()) return instance.shouldApply(cameraSubmersionType, entity);
String className = instance.getClass().getSimpleName();
if ((className.equals("BlindnessEffectFogModifier") && !noRender.blindnessEffect.isEnabled())
|| (className.equals("DarknessEffectFogModifier") && !noRender.darknessEffect.isEnabled())
if ((className.equals("BlindnessEffectFogModifier") && !noRender.blindnessEffect.getValue())
|| (className.equals("DarknessEffectFogModifier") && !noRender.darknessEffect.getValue())
|| ((className.equals("LavaFogModifier") || className.equals("WaterFogModifier")
|| className.equals("PowederSnowFogModifier")) && !noRender.fluidOverlay.isEnabled()))
|| className.equals("PowederSnowFogModifier")) && !noRender.fluidOverlay.getValue()))
return false;
return instance.shouldApply(cameraSubmersionType, entity);
@@ -44,7 +44,7 @@ public abstract class FogRendererMixin {
@ModifyReturnValue(method = "getFogColor", at = @At("RETURN"))
private Vector4f modifyLavaFog(Vector4f original, Camera camera) {
if (noRender.isEnabled() && !noRender.fluidOverlay.isEnabled() &&
if (noRender.isEnabled() && !noRender.fluidOverlay.getValue() &&
(camera.getSubmersionType() == CameraSubmersionType.LAVA
|| camera.getSubmersionType() == CameraSubmersionType.WATER))
return new Vector4f(original.x, original.y, original.z, 0f);
@@ -54,6 +54,6 @@ public abstract class FogRendererMixin {
@ModifyExpressionValue(method = "getFogColor", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getUnderwaterVisibility()F"))
private float noRenderUnderwaterFog(float original) {
return (noRender.isEnabled() && !noRender.fluidOverlay.isEnabled()) ? 0 : original;
return (noRender.isEnabled() && !noRender.fluidOverlay.getValue()) ? 0 : original;
}
}
@@ -0,0 +1,38 @@
package me.retucio.sputnik.mixin;
import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.render.Fonts;
import net.minecraft.client.font.FontManager;
import net.minecraft.client.font.FontStorage;
import net.minecraft.text.StyleSpriteSource;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(FontManager.class)
public abstract class FontManagerMixin {
@Shadow
public abstract FontStorage getStorageInternal(Identifier id);
@Inject(method = "getStorageInternal", at = @At("HEAD"), cancellable = true)
private void onGetStorageInternal(Identifier id, CallbackInfoReturnable<FontStorage> cir) {
Fonts fonts = ModuleManager.INSTANCE.getModuleByClass(Fonts.class);
if (!fonts.isEnabled()) return;
if (id.equals(StyleSpriteSource.Font.DEFAULT.id())) {
cir.setReturnValue(getStorageInternal(
Identifier.of(
Sputnik.MOD_ID,
fonts.font.getValue())
));
}
}
}
@@ -4,6 +4,7 @@ package me.retucio.sputnik.mixin;
import me.retucio.sputnik.event.events.GetFOVEvent;
import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.camera.Freecam;
import me.retucio.sputnik.module.modules.misc.UnfocusedCpu;
import me.retucio.sputnik.module.modules.render.NoRender;
import me.retucio.sputnik.module.modules.camera.Zoom;
import me.retucio.sputnik.util.interfaces.IVec3d;
@@ -11,6 +12,7 @@ import me.retucio.sputnik.util.interfaces.IVec3d;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.BufferBuilderStorage;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.RenderTickCounter;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.client.render.item.HeldItemRenderer;
import net.minecraft.entity.Entity;
@@ -22,6 +24,7 @@ import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
@@ -29,6 +32,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import static me.retucio.sputnik.Sputnik.EVENT_BUS;
import static me.retucio.sputnik.Sputnik.mc;
@Mixin(GameRenderer.class)
@@ -64,6 +68,12 @@ public abstract class GameRendererMixin {
return EVENT_BUS.post(new GetFOVEvent(original)).getFov();
}
@Inject(method = "render", at = @At("HEAD"), cancellable = true)
private void avoidRenderingUnfocusedCpu(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci) {
if (ModuleManager.INSTANCE.getModuleByClass(UnfocusedCpu.class).isEnabled() && !mc.isWindowFocused())
ci.cancel();
}
@Inject(method = "updateCrosshairTarget", at = @At("HEAD"), cancellable = true)
private void updateTargetedEntityInvoke(float tickDelta, CallbackInfo ci) {
if ((freecam.isEnabled()) && client.getCameraEntity() != null && !freecamDone) {
@@ -110,13 +120,13 @@ public abstract class GameRendererMixin {
@Inject(method = "renderHand", at = @At("HEAD"), cancellable = true)
private void renderHand(float tickProgress, boolean sleeping, Matrix4f positionMatrix, CallbackInfo ci) {
if ((zoom.isEnabled() && !zoom.showHands.isEnabled())
|| (freecam.isEnabled() && !freecam.renderHands.isEnabled()))
if ((zoom.isEnabled() && !zoom.showHands.getValue())
|| (freecam.isEnabled() && !freecam.renderHands.getValue()))
ci.cancel();
}
@ModifyVariable(method = "renderWorld", ordinal = 6, at = @At(value = "STORE"))
private float noRenderNauseaDistortion(float scaledNauseaEffectFactor) {
return (noRender.isEnabled() && !noRender.nauseaEffect.isEnabled()) ? 0 : scaledNauseaEffectFactor;
return (noRender.isEnabled() && !noRender.nauseaEffect.getValue()) ? 0 : scaledNauseaEffectFactor;
}
}
@@ -65,19 +65,19 @@ public abstract class HeldItemRendererMixin {
@ModifyReturnValue(method = "shouldSkipHandAnimationOnSwap", at = @At("RETURN"))
private boolean modifySkipSwapAnimation(boolean original) {
return original || (handView.isEnabled() && handView.skipSwapping.isEnabled());
return original || (handView.isEnabled() && handView.skipSwapping.getValue());
}
@Inject(method = "applyEatOrDrinkTransformation", at = @At(value = "INVOKE", target = "Ljava/lang/Math;pow(DD)D", shift = At.Shift.BEFORE), cancellable = true)
private void cancelTransformations(MatrixStack matrices, float tickDelta, Arm arm, ItemStack stack, PlayerEntity player, CallbackInfo ci) {
if (handView.isEnabled() && handView.noFood.isEnabled()) ci.cancel();
if (handView.isEnabled() && handView.noFood.getValue()) ci.cancel();
}
@ModifyArg(method = "updateHeldItems", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;clamp(FFF)F", ordinal = 2), index = 0)
private float modifyEquipProgressMainhand(float value) {
if (mc.player == null) return value;
float progress = mc.player.getAttackCooldownProgress(1);
float modified = handView.isEnabled() && handView.oldAnimations.isEnabled() ? 1 : (float) Math.pow(progress, 3);
float modified = handView.isEnabled() && handView.oldAnimations.getValue() ? 1 : (float) Math.pow(progress, 3);
return (shouldSkipHandAnimationOnSwap(mainHand, mc.player.getMainHandStack()) ? modified : 0) - equipProgressMainHand;
}
@@ -40,32 +40,32 @@ public abstract class InGameHudMixin {
@Inject(method = "renderScoreboardSidebar*", at = @At("HEAD"), cancellable = true)
private void noRenderScoreboard(CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.scoreboard.isEnabled()) ci.cancel();
if (noRender.isEnabled() && !noRender.scoreboard.getValue()) ci.cancel();
}
@Inject(method = "renderTitleAndSubtitle", at = @At("HEAD"), cancellable = true)
private void noRenderTitles(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.titles.isEnabled()) ci.cancel();
if (noRender.isEnabled() && !noRender.titles.getValue()) ci.cancel();
}
@Inject(method = "renderNauseaOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderNausea(DrawContext context, float nauseaStrength, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.nauseaEffect.isEnabled()) ci.cancel();
if (noRender.isEnabled() && !noRender.nauseaEffect.getValue()) ci.cancel();
}
@Inject(method = "renderSpyglassOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderSpyglass(DrawContext context, float scale, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.spyglassOverlay.isEnabled()) ci.cancel();
if (noRender.isEnabled() && !noRender.spyglassOverlay.getValue()) ci.cancel();
}
@Inject(method = "renderPortalOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderPortal(DrawContext context, float nauseaStrength, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.portalOverlay.isEnabled()) ci.cancel();
if (noRender.isEnabled() && !noRender.portalOverlay.getValue()) ci.cancel();
}
@Inject(method = "renderOverlay", at = @At("HEAD"), cancellable = true)
private void noRenderPumpkinBlur(DrawContext context, Identifier texture, float opacity, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.pumpkinOverlay.isEnabled() && texture.getPath().equals("textures/misc/pumpkinblur.png")) ci.cancel();
if (noRender.isEnabled() && !noRender.pumpkinOverlay.getValue() && texture.getPath().equals("textures/misc/pumpkinblur.png")) ci.cancel();
}
@@ -84,6 +84,6 @@ public abstract class InGameHudMixin {
@Inject(method = "clear", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;clear(Z)V"), cancellable = true)
private void onClear(CallbackInfo ci) {
ChatPlus chatPlus = ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class);
if (chatPlus.isEnabled() && chatPlus.keepHistory.isEnabled()) ci.cancel();
if (chatPlus.isEnabled() && chatPlus.keepHistory.getValue()) ci.cancel();
}
}
@@ -27,11 +27,11 @@ public abstract class InGameOverlayRendererMixin {
@Inject(method = "renderFireOverlay", at = @At("HEAD"), cancellable = true)
private static void noRenderFireOverlay(MatrixStack matrices, VertexConsumerProvider vertexConsumers, Sprite sprite, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.fireOverlay.isEnabled()) ci.cancel();
if (noRender.isEnabled() && !noRender.fireOverlay.getValue()) ci.cancel();
}
@Inject(method = "renderUnderwaterOverlay", at = @At("HEAD"), cancellable = true)
private static void noRenderUnderwaterOverlay(MinecraftClient client, MatrixStack matrices, VertexConsumerProvider vertexConsumers, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.fluidOverlay.isEnabled()) ci.cancel();
if (noRender.isEnabled() && !noRender.fluidOverlay.getValue()) ci.cancel();
}
}
@@ -28,7 +28,7 @@ public abstract class ItemEntityMixin {
if (!name.equals(original)) name = name.formatted(Formatting.ITALIC);
if (nametags.countItems.isEnabled()) {
if (nametags.countItems.getValue()) {
if (count > 1) return name.copy().append(" x" + count);
return name;
}
@@ -23,7 +23,7 @@ public abstract class ItemMixin {
@Inject(method = "appendTooltip", at = @At("HEAD"))
private void onAppendTooltip(ItemStack stack, Item.TooltipContext context, TooltipDisplayComponent displayComponent, Consumer<Text> textConsumer, TooltipType type, CallbackInfo ci) {
ShulkerPeek shulkerPeek = ModuleManager.INSTANCE.getModuleByClass(ShulkerPeek.class);
if (!shulkerPeek.isEnabled() || !shulkerPeek.showTooltips.isEnabled()) return;
if (!shulkerPeek.isEnabled() || !shulkerPeek.showTooltips.getValue()) return;
if (stack.getItem() instanceof BlockItem blockItem && blockItem.getBlock() instanceof ShulkerBoxBlock) {
if (ShulkerPeek.isShulkerEmpty(stack)) {
@@ -16,7 +16,7 @@ public abstract class KeyInputMixin extends Input {
@Inject(method = "tick", at = @At("TAIL"))
private void isPressed(CallbackInfo ci) {
Freecam freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
if (freecam.isEnabled() && freecam.stayCrouching.isEnabled() && freecam.isCrouching())
if (freecam.isEnabled() && freecam.stayCrouching.getValue() && freecam.isCrouching())
playerInput = new PlayerInput(
false, false,
false, false,
@@ -55,6 +55,6 @@ public abstract class LightmapTextureManagerMixin {
@Inject(method = "getDarkness", at = @At("HEAD"), cancellable = true)
private void noRenderDarkness(LivingEntity entity, float factor, float tickProgress, CallbackInfoReturnable<Float> cir) {
if (noRender.isEnabled() && !noRender.darknessEffect.isEnabled()) cir.setReturnValue(0f);
if (noRender.isEnabled() && !noRender.darknessEffect.getValue()) cir.setReturnValue(0f);
}
}
@@ -1,7 +1,8 @@
package me.retucio.sputnik.mixin;
import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.player.ElytraBounce;
import me.retucio.sputnik.module.modules.movement.ElytraBounce;
import me.retucio.sputnik.module.modules.movement.Step;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.sound.SoundCategory;
@@ -12,6 +13,7 @@ import org.spongepowered.asm.mixin.Unique;
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.CallbackInfoReturnable;
import static me.retucio.sputnik.Sputnik.mc;
@@ -26,7 +28,7 @@ public abstract class LivingEntityMixin {
@SuppressWarnings("ConstantConditions")
@Inject(method = "tickMovement", at = @At("TAIL"))
public void recastIfLanded(CallbackInfo ci) {
private void recastIfLanded(CallbackInfo ci) {
ElytraBounce bounce = ModuleManager.INSTANCE.getModuleByClass(ElytraBounce.class);
if (!((Object) this instanceof ClientPlayerEntity)
@@ -47,4 +49,11 @@ public abstract class LivingEntityMixin {
prevElytra = elytra;
}
@Inject(method = "getStepHeight", at = @At("RETURN"), cancellable = true)
private void step(CallbackInfoReturnable<Float> cir) {
Step step = ModuleManager.INSTANCE.getModuleByClass(Step.class);
if (step.isEnabled()) cir.setReturnValue(step.height.getFloatValue());
}
}
@@ -40,12 +40,12 @@ public abstract class LivingEntityRendererMixin<T extends LivingEntity> {
@ModifyExpressionValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;isSneaky()Z"))
private boolean renderSneakingPlayerNametags(boolean original) {
return (nametags.isEnabled() && nametags.alwaysVisible.isEnabled()) || original;
return (nametags.isEnabled() && nametags.alwaysVisible.getValue()) || original;
}
@ModifyExpressionValue(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;isInvisibleTo(Lnet/minecraft/entity/player/PlayerEntity;)Z"))
private boolean renderInvisPlayerNametags(boolean original) {
if (nametags.isEnabled() && nametags.alwaysVisible.isEnabled()) return false;
if (nametags.isEnabled() && nametags.alwaysVisible.getValue()) return false;
else return original;
}
@@ -58,7 +58,7 @@ public abstract class LivingEntityRendererMixin<T extends LivingEntity> {
@Inject(method = "hasLabel(Lnet/minecraft/entity/LivingEntity;D)Z", at = @At("RETURN"), cancellable = true)
private void renderSelfNametag(T livingEntity, double d, CallbackInfoReturnable<Boolean> cir) {
if (livingEntity instanceof PlayerEntity player) {
if (player == mc.player && nametags.showSelf.isEnabled()) {
if (player == mc.player && nametags.showSelf.getValue()) {
cir.setReturnValue(true);
cir.cancel();
}
@@ -14,9 +14,9 @@ import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@@ -27,6 +27,12 @@ public abstract class MinecraftClientMixin {
@Shadow
private int itemUseCooldown;
@Shadow
public int attackCooldown;
// eventos
@Inject(method = "tick", at = @At("HEAD"))
private void onTickPre(CallbackInfo ci) {
Sputnik.INSTANCE.onTick();
@@ -49,9 +55,10 @@ public abstract class MinecraftClientMixin {
if (event.isCancelled()) ci.cancel();
}
@Inject(method = "isTelemetryEnabledByApi", at = @At("RETURN"), cancellable = true)
private void disableMicropenisTelemetryShi(CallbackInfoReturnable<Boolean> cir) {
cir.setReturnValue(false);
@Inject(method = "joinWorld", at = @At("HEAD"), cancellable = true)
private void onJoinWorld(ClientWorld world, CallbackInfo ci) {
JoinWorldEvent event = Sputnik.EVENT_BUS.post(new JoinWorldEvent(world));
if (event.isCancelled()) ci.cancel();
}
@Inject(method = "doItemUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getStackInHand(Lnet/minecraft/util/Hand;)Lnet/minecraft/item/ItemStack;"), cancellable = true)
@@ -61,16 +68,21 @@ public abstract class MinecraftClientMixin {
if (event.isCancelled()) ci.cancel();
}
// telemetría
@Inject(method = "isTelemetryEnabledByApi", at = @At("RETURN"), cancellable = true)
private void disableMicropenisTelemetryShi(CallbackInfoReturnable<Boolean> cir) {
cir.setReturnValue(false);
}
// precoz
@Inject(method = "doItemUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;isItemEnabled(Lnet/minecraft/resource/featuretoggle/FeatureSet;)Z"))
private void modifyItemUseCooldown(CallbackInfo ci, @Local ItemStack stack) {
FastUse fastUse = ModuleManager.INSTANCE.getModuleByClass(FastUse.class);
if (!fastUse.isEnabled()) return;
itemUseCooldown = fastUse.getCooldown(stack);
}
@Inject(method = "joinWorld", at = @At("HEAD"), cancellable = true)
private void onJoinWorld(ClientWorld world, CallbackInfo ci) {
JoinWorldEvent event = Sputnik.EVENT_BUS.post(new JoinWorldEvent(world));
if (event.isCancelled()) ci.cancel();
}
}
@@ -26,7 +26,7 @@ public abstract class PlayerEntityMixin extends LivingEntity {
@ModifyReturnValue(method = "getDisplayName", at = @At("RETURN"))
private Text addHealthIndicator(Text original) {
Nametags nametags = ModuleManager.INSTANCE.getModuleByClass(Nametags.class);
if (!nametags.isEnabled() || !nametags.health.isEnabled()) return original;
if (!nametags.isEnabled() || !nametags.health.getValue()) return original;
float health = getHealth();
float absorption = getAbsorptionAmount();
@@ -26,13 +26,13 @@ public abstract class SkyRendererMixin {
@Inject(method = "renderSun", at = @At("HEAD"), cancellable = true)
private void onRenderSun(float alpha, MatrixStack matrices, CallbackInfo ci) {
if (timeChanger.isEnabled() && !timeChanger.renderSun.isEnabled()) ci.cancel();
if (timeChanger.isEnabled() && !timeChanger.renderSun.getValue()) ci.cancel();
}
@Inject(method = "renderMoon", at = @At("HEAD"), cancellable = true)
private void onRenderMoon(MoonPhase moonPhase, float alpha, MatrixStack matrices, CallbackInfo ci) {
if (!timeChanger.isEnabled()) return;
if (!timeChanger.renderMoon.isEnabled()) ci.cancel();
if (!timeChanger.renderMoon.getValue()) ci.cancel();
}
@ModifyArg(method = "renderCelestialBodies", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/SkyRendering;renderMoon(Lnet/minecraft/world/MoonPhase;FLnet/minecraft/client/util/math/MatrixStack;)V"))
@@ -45,12 +45,12 @@ public abstract class SkyRendererMixin {
@Inject(method = "renderStars", at = @At("HEAD"), cancellable = true)
private void onRenderStars(float brightness, MatrixStack matrices, CallbackInfo ci) {
if (timeChanger.isEnabled() && !timeChanger.renderStars.isEnabled()) ci.cancel();
if (timeChanger.isEnabled() && !timeChanger.renderStars.getValue()) ci.cancel();
}
@Inject(method = "drawEndLightFlash", at = @At("HEAD"), cancellable = true)
private void onEndFlash(MatrixStack matrixStack, float f, float skyFactor, float pitch, CallbackInfo ci) {
NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
if (noRender.isEnabled() && !noRender.endFlashes.isEnabled()) ci.cancel();
if (noRender.isEnabled() && !noRender.endFlashes.getValue()) ci.cancel();
}
}
@@ -21,8 +21,8 @@ public abstract class StatusEffectFogModifierMixin {
public boolean noRenderBadEffects(boolean original) {
NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
if (!noRender.isEnabled()) return original;
if (getStatusEffect() == StatusEffects.BLINDNESS && !noRender.blindnessEffect.isEnabled()) return false;
if (getStatusEffect() == StatusEffects.DARKNESS && !noRender.darknessEffect.isEnabled()) return false;
if (getStatusEffect() == StatusEffects.BLINDNESS && !noRender.blindnessEffect.getValue()) return false;
if (getStatusEffect() == StatusEffects.DARKNESS && !noRender.darknessEffect.getValue()) return false;
return original;
}
}
@@ -13,6 +13,6 @@ public abstract class StringHelperMixin {
@ModifyArg(method = "truncateChat", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/StringHelper;truncate(Ljava/lang/String;IZ)Ljava/lang/String;"), index = 1)
private static int onTruncate(int maxLength) {
ChatPlus chatPlus = ModuleManager.INSTANCE.getModuleByClass(ChatPlus.class);
return ((chatPlus.isEnabled() && chatPlus.noCharLimit.isEnabled()) ? Integer.MAX_VALUE : maxLength);
return ((chatPlus.isEnabled() && chatPlus.noCharLimit.getValue()) ? Integer.MAX_VALUE : maxLength);
}
}
@@ -13,7 +13,7 @@ public abstract class StuckArrowsFeatureRendererMixin {
@ModifyReturnValue(method = "getObjectCount", at = @At("RETURN"))
private int noRenderStuckArrows(int original) {
NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
if (noRender.isEnabled() && !noRender.stuckArrows.isEnabled()) return 0;
if (noRender.isEnabled() && !noRender.stuckArrows.getValue()) return 0;
return original;
}
}
@@ -24,17 +24,17 @@ public abstract class TextRendererDrawerMixin {
@Redirect(method = "accept(ILnet/minecraft/text/Style;Lnet/minecraft/client/font/BakedGlyph;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isBold()Z"))
private boolean noRenderBold(Style style) {
return !(noRender.isEnabled() && !noRender.bold.isEnabled()) && style.isBold();
return !(noRender.isEnabled() && !noRender.bold.getValue()) && style.isBold();
}
@Redirect(method = "accept(ILnet/minecraft/text/Style;Lnet/minecraft/client/font/BakedGlyph;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isUnderlined()Z"))
private boolean noRenderUnderlined(Style style) {
return !(noRender.isEnabled() && !noRender.underlined.isEnabled()) && style.isUnderlined();
return !(noRender.isEnabled() && !noRender.underlined.getValue()) && style.isUnderlined();
}
@Redirect(method = "accept(ILnet/minecraft/text/Style;Lnet/minecraft/client/font/BakedGlyph;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isStrikethrough()Z"))
private boolean noRenderStrikethrough(Style style) {
return !(noRender.isEnabled() && !noRender.strikethrough.isEnabled()) && style.isStrikethrough();
return !(noRender.isEnabled() && !noRender.strikethrough.getValue()) && style.isStrikethrough();
}
@ModifyArg(method = "accept(ILnet/minecraft/text/Style;Lnet/minecraft/client/font/BakedGlyph;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/TextRenderer$Drawer;getRenderColor(Lnet/minecraft/text/TextColor;)I"))
@@ -13,6 +13,6 @@ public abstract class TextRendererMixin {
@ModifyExpressionValue(method = "getGlyph", at = @At(value = "INVOKE", target = "Lnet/minecraft/text/Style;isObfuscated()Z"))
private boolean noRenderMTS(boolean original) {
NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
return (!noRender.isEnabled() || noRender.scrambledText.isEnabled()) && original;
return (!noRender.isEnabled() || noRender.scrambledText.getValue()) && original;
}
}
@@ -0,0 +1,39 @@
package me.retucio.sputnik.mixin;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import me.retucio.sputnik.module.ModuleManager;
import me.retucio.sputnik.module.modules.movement.TridentBoost;
import net.minecraft.item.Item;
import net.minecraft.item.TridentItem;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArgs;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.invoke.arg.Args;
@Mixin(TridentItem.class)
public abstract class TridentItemMixin {
@ModifyArgs(method = "onStoppedUsing", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;addVelocity(DDD)V"))
private void modifyVelocity(Args args) {
TridentBoost tridentBoost = ModuleManager.INSTANCE.getModuleByClass(TridentBoost.class);
if (!tridentBoost.isEnabled()) return;
args.set(0, (double) args.get(0) * tridentBoost.multiplier.getValue());
args.set(1, (double) args.get(1) * tridentBoost.multiplier.getValue());
args.set(2, (double) args.get(2) * tridentBoost.multiplier.getValue());
}
@ModifyExpressionValue(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;isTouchingWaterOrRain()Z"))
private boolean allowUseOutOfWaterPre(boolean original) {
TridentBoost tridentBoost = ModuleManager.INSTANCE.getModuleByClass(TridentBoost.class);
return (tridentBoost.outOfWater.getValue() && tridentBoost.isEnabled()) || original;
}
@ModifyExpressionValue(method = "onStoppedUsing", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;isTouchingWaterOrRain()Z"))
private boolean allowUseOutOfWaterPost(boolean original) {
TridentBoost tridentBoost = ModuleManager.INSTANCE.getModuleByClass(TridentBoost.class);
return (tridentBoost.outOfWater.getValue() && tridentBoost.isEnabled()) || original;
}
}
@@ -29,14 +29,14 @@ public abstract class WeatherRenderingMixin {
@Inject(method = "addParticlesAndSound", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;addParticleClient(Lnet/minecraft/particle/ParticleEffect;DDDDDD)V"), cancellable = true)
private void noRainParticles(ClientWorld world, Camera camera, int ticks, ParticlesMode particlesMode, int weatherRadius, CallbackInfo ci) {
if (noRender.isEnabled() && !noRender.rain.isEnabled()) ci.cancel();
if (noRender.isEnabled() && !noRender.rain.getValue()) ci.cancel();
}
@Inject(method = "renderPrecipitation", at = @At("HEAD"))
private void noRenderRainAndSnow(VertexConsumerProvider vertexConsumers, Vec3d pos, WeatherRenderState weatherRenderState, CallbackInfo ci) {
if (noRender.isEnabled()) {
if (!noRender.rain.isEnabled()) weatherRenderState.rainPieces.clear();
if (!noRender.snow.isEnabled()) weatherRenderState.snowPieces.clear();
if (!noRender.rain.getValue()) weatherRenderState.rainPieces.clear();
if (!noRender.snow.getValue()) weatherRenderState.snowPieces.clear();
}
}
}
@@ -12,16 +12,12 @@ import net.minecraft.client.render.*;
import net.minecraft.client.render.state.WorldRenderState;
import net.minecraft.client.util.ObjectAllocator;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.ColorHelper;
import net.minecraft.util.math.RotationAxis;
import net.minecraft.util.profiler.Profiler;
import org.joml.Matrix4f;
import org.joml.Vector4f;
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.ModifyArg;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@@ -56,21 +52,28 @@ public abstract class WorldRendererMixin {
@Inject(method = "renderTargetBlockOutline", at = @At("HEAD"), cancellable = true)
private void noRenderBlockOutlinesFreecam(VertexConsumerProvider.Immediate immediate, MatrixStack matrices, boolean renderBlockOutline, WorldRenderState renderStates, CallbackInfo ci) {
Freecam freecam = ModuleManager.INSTANCE.getModuleByClass(Freecam.class);
if (freecam.isEnabled() && !freecam.blockOutlines.isEnabled()) ci.cancel();
if (freecam.isEnabled() && !freecam.blockOutlines.getValue()) ci.cancel();
}
@Inject(method = "hasBlindnessOrDarkness(Lnet/minecraft/client/render/Camera;)Z", at = @At("HEAD"), cancellable = true)
private void hasBlindnessOrDarkness(Camera camera, CallbackInfoReturnable<Boolean> cir) {
NoRender noRender = ModuleManager.INSTANCE.getModuleByClass(NoRender.class);
if (!noRender.isEnabled()) return;
if (!noRender.blindnessEffect.isEnabled() || !noRender.darknessEffect.isEnabled()) cir.setReturnValue(null);
if (!noRender.blindnessEffect.getValue() || !noRender.darknessEffect.getValue()) cir.setReturnValue(null);
}
@Redirect(method = "renderTargetBlockOutline", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/ColorHelper;toAlpha(I)I"))
private int modifyBlockOutlineColor(int alpha) {
BlockOutline outline = ModuleManager.INSTANCE.getModuleByClass(BlockOutline.class);
if (!outline.isEnabled()) return ColorHelper.toAlpha(alpha);
@ModifyArg(method = "renderTargetBlockOutline", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;drawBlockOutline(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumer;DDDLnet/minecraft/client/render/state/OutlineRenderState;IF)V"))
private int modifyBlockOutlineColor(int original) {
BlockOutline outline = ModuleManager.INSTANCE.getModuleByClass(BlockOutline.class);
if (!outline.isEnabled()) return original;
return outline.color.getRGB();
}
@ModifyArg(method = "renderTargetBlockOutline", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;drawBlockOutline(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumer;DDDLnet/minecraft/client/render/state/OutlineRenderState;IF)V"))
private float modifyBlockOutlineLineWidth(float original) {
BlockOutline outline = ModuleManager.INSTANCE.getModuleByClass(BlockOutline.class);
if (!outline.isEnabled()) return original;
return outline.lineWidth.getFloatValue();
}
}
@@ -0,0 +1,13 @@
package me.retucio.sputnik.mixin.accessor;
import net.minecraft.block.AbstractBlock;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(AbstractBlock.class)
public interface AbstractBlockAccessor {
@Mutable @Accessor("slipperiness")
void setSlipperiness(float slipperiness);
}
@@ -4,6 +4,7 @@ public enum Category {
PLAYER("jugador"),
WORLD("mundo"),
MOVEMENT("movimiento"),
CAMERA("cámara"),
RENDER("renderizado"),
@@ -11,7 +12,9 @@ public enum Category {
NETWORK("red"),
CLIENT("cliente"),
MISC("misc.");
MISC("misc."),
ALL("todos");
private final String name;
Category(String name) { this.name = name; }
@@ -16,7 +16,6 @@ import org.lwjgl.glfw.GLFW;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
// clase base para los módulos
public class Module {
@@ -53,12 +52,12 @@ public class Module {
this.description = description;
this.category = category;
sgGeneral.addAll(bind, keyMode, notify);
this.bind.setDefaultKey(key);
this.bind.setDefaultValue(key);
// puto marcos
if (ConfigManager.getConfig().settings
.get(this.getName() + ":" + bind.getName()) == null)
this.bind.setKey(key);
this.bind.setValue(key);
}
@@ -83,8 +82,12 @@ public class Module {
return null;
}
public List<Setting> getSettings() {
List<Setting> settings = new ArrayList<>();
public SettingGroup getSgGeneral() {
return sgGeneral;
}
public List<Setting<?>> getSettings() {
List<Setting<?>> settings = new ArrayList<>();
sgs.forEach(sg -> sg.forEach(settings::add));
return settings;
}
@@ -99,7 +102,7 @@ public class Module {
}
public void onEnable() {
if (notify.isEnabled()) ChatUtil.info(getName() + " fue activado");
if (notify.getValue()) ChatUtil.info(getName() + " fue activado");
for (Method method : getClass().getDeclaredMethods())
if (method.isAnnotationPresent(SubscribeEvent.class)) {
Sputnik.EVENT_BUS.register(this);
@@ -109,7 +112,7 @@ public class Module {
}
public void onDisable() {
if (notify.isEnabled()) ChatUtil.info(getName() + " fue desactivado");
if (notify.getValue()) ChatUtil.info(getName() + " fue desactivado");
if (Sputnik.EVENT_BUS.isRegistered(this))
Sputnik.EVENT_BUS.unregister(this);
Sputnik.EVENT_BUS.post(new ToggleModuleEvent(this));
@@ -165,16 +168,16 @@ public class Module {
}
public int getKey() {
return bind.getKey();
return bind.getValue();
}
public void setKey(int key) {
bind.setKey(key);
bind.setValue(key);
}
public void assignKey(int key) {
bind.setDefaultKey(key);
bind.setKey(key);
bind.setDefaultValue(key);
bind.setValue(key);
}
public KeySetting getBind() {
@@ -2,15 +2,19 @@ package me.retucio.sputnik.module;
import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.event.SubscribeEvent;
import me.retucio.sputnik.module.modules.client.DiscordRPC;
import me.retucio.sputnik.module.modules.client.HUD;
import me.retucio.sputnik.module.modules.camera.*;
import me.retucio.sputnik.module.modules.misc.*;
import me.retucio.sputnik.module.modules.movement.*;
import me.retucio.sputnik.module.modules.network.*;
import me.retucio.sputnik.module.modules.player.*;
import me.retucio.sputnik.module.modules.render.*;
import me.retucio.sputnik.module.modules.render.CritsPlus;
import me.retucio.sputnik.module.modules.world.*;
import me.retucio.sputnik.util.MiscUtil;
import java.awt.*;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Comparator;
@@ -28,55 +32,18 @@ public class ModuleManager {
addModules();
}
// por orden alfabético y todo, flipas
private void addModules() {
modules.add(new AntiInvis());
modules.add(new AnvilFont());
modules.add(new AttributeSwapper());
modules.add(new AutoSign());
modules.add(new BlockESP());
modules.add(new BlockOutline());
modules.add(new BossbarStack());
modules.add(new BreakingProgress());
modules.add(new BungeecordSpoofer());
modules.add(new Capes());
modules.add(new ChatPlus());
modules.add(new ColoredSigns());
modules.add(new CritsPlus());
modules.add(new DamageOverlay());
modules.add(new ElytraBounce());
modules.add(new FakePlayer());
modules.add(new FastUse());
modules.add(new Freecam());
modules.add(new Freelook());
modules.add(new Fullbright());
modules.add(new GlintPlus());
modules.add(new HandView());
modules.add(new Headhitters());
modules.add(new HUD());
modules.add(new InventoryPlus());
modules.add(new LightOverlay());
modules.add(new LogoutSpots());
modules.add(new Nametags());
modules.add(new NoMiningInterruptions());
modules.add(new NoRender());
modules.add(new Offhand());
modules.add(new PacketDelay());
modules.add(new PerspectivePlus());
modules.add(new PortalGUI());
modules.add(new Racist());
modules.add(new Reconnect());
modules.add(new Rotations());
modules.add(new RPackBypass());
modules.add(new SafeWalk());
modules.add(new ScreenshotPlus());
modules.add(new ShulkerPeek());
modules.add(new TimeChanger());
modules.add(new UIMove());
modules.add(new WarnLowDurability());
modules.add(new Zoom());
// añadir los módulos
addCamera();
addClient();
addMisc();
addMovement();
addNetwork();
addPlayer();
addRender();
addWorld();
modules.sort(Comparator.comparing(module -> module.getName().toLowerCase()));
modules.sort(Comparator.comparing(module -> MiscUtil.removeAccentMarks(module.getName().toLowerCase())));
// registrar los "listeners" necesarios
for (Module module : getEnabledModules()) {
@@ -89,6 +56,102 @@ public class ModuleManager {
}
}
private void add(Module module) {
modules.add(module);
}
private void addCamera() {
add(new Freecam());
add(new Freelook());
add(new Fullbright());
add(new PerspectivePlus());
add(new Rotations());
add(new Zoom());
}
private void addClient() {
add(new DiscordRPC());
add(new HUD());
}
private void addMisc() {
add(new AntiInvis());
add(new AnvilFont());
add(new BossbarStack());
add(new ChatPlus());
add(new FakePlayer());
add(new ScreenshotPlus());
add(new ShulkerPeek());
add(new UnfocusedCpu());
}
private void addMovement() {
add(new BoatFly());
add(new Dolphin());
add(new ElytraBounce());
add(new ElytraFly());
add(new Headhitters());
add(new InfiniteElytra());
add(new Jesus());
add(new ReverseStep());
add(new SafeWalk());
add(new Slippy());
add(new Step());
add(new TridentBoost());
}
private void addNetwork() {
add(new BungeecordSpoofer());
add(new LogoutSpots());
add(new PacketDelay());
add(new PacketMine());
add(new Reconnect());
add(new RPackBypass());
}
private void addPlayer() {
add(new AttributeSwapper());
add(new Capes());
add(new FastUse());
add(new HandView());
add(new InventoryPlus());
add(new MaceKill());
add(new Offhand());
add(new PortalGUI());
add(new UIMove());
add(new WarnLowDurability());
}
private void addRender() {
add(new BlockESP());
add(new BlockOutline());
add(new BreakingProgress());
add(new CritsPlus());
add(new DamageOverlay());
add(new Fonts());
add(new GlintPlus());
add(new Nametags());
add(new NoRender());
add(new Particles());
}
private void addWorld() {
add(new AutoSign());
add(new BlockInfo());
add(new ColoredSigns());
add(new LightOverlay());
add(new NoMiningInterruptions());
add(new Racist());
add(new StrongholdTriangulator());
add(new TimeChanger());
}
// para obtener módulos más fácilmente (por nombre, clase, o la lista completa)
public List<Module> getModules() {
@@ -105,7 +168,8 @@ public class ModuleManager {
public Module getModuleByName(String name) {
for (Module module : modules)
if (module.getName().equalsIgnoreCase(name)) return module;
if (MiscUtil.removeAccentMarks(module.getName()).equalsIgnoreCase(name))
return module;
return null;
}
@@ -87,7 +87,7 @@ public class Freecam extends Module {
fovScale = mc.options.getFovEffectScale().getValue();
viewBobbing = mc.options.getBobView().getValue();
if (staticView.isEnabled()) {
if (staticView.getValue()) {
mc.options.getFovEffectScale().setValue(0D);
mc.options.getBobView().setValue(false);
}
@@ -119,25 +119,25 @@ public class Freecam extends Module {
down = KeyUtil.isKeyDown(mc.options.sneakKey);
unpress();
if (reloadChunks.isEnabled()) mc.worldRenderer.reload();
if (reloadChunks.getValue()) mc.worldRenderer.reload();
super.onEnable();
}
@Override
public void onDisable() {
if (reloadChunks.isEnabled()) mc.execute(mc.worldRenderer::reload);
if (reloadChunks.getValue()) mc.execute(mc.worldRenderer::reload);
mc.options.setPerspective(perspective);
crouching = false;
if (staticView.isEnabled()) {
if (staticView.getValue()) {
mc.options.getFovEffectScale().setValue(fovScale);
mc.options.getBobView().setValue(viewBobbing);
}
// para no flaggear el anticheat, cancelar cualquier acción dejada a medias estando en modo libre
if (cancelActionPackets.isEnabled()) {
if (cancelActionPackets.getValue()) {
if (mc.interactionManager != null)
mc.interactionManager.cancelBlockBreaking();
@@ -199,7 +199,7 @@ public class Freecam extends Module {
@SubscribeEvent
public void onSendPacket(PacketEvent.Send event) {
if (!isEnabled() || !cancelActionPackets.isEnabled()) return;
if (!isEnabled() || !cancelActionPackets.getValue()) return;
if (event.getStage() != Stage.PRE) return;
Packet<?> packet = event.getPacket();
@@ -279,7 +279,7 @@ public class Freecam extends Module {
@SubscribeEvent
private void onMouseScroll(MouseScrollEvent event) {
if (scrollSens.getValue() > 0 && mc.currentScreen == null && KeyUtil.isKeyDown(scrollKey.getKey())) {
if (scrollSens.getValue() > 0 && mc.currentScreen == null && KeyUtil.isKeyDown(scrollKey.getValue())) {
speed += event.getVertical() / 4 * (scrollSens.getValue() * speed);
if (speed < 0.1) speed = 0.1;
event.cancel();
@@ -304,7 +304,7 @@ public class Freecam extends Module {
if (mc.player.getId() == packet.playerId())
toggle();
} else if (event.getPacket() instanceof HealthUpdateS2CPacket packet) {
if (mc.player.getHealth() - packet.getHealth() > 0 && toggleOnDamage.isEnabled()) {
if (mc.player.getHealth() - packet.getHealth() > 0 && toggleOnDamage.getValue()) {
ChatUtil.info("cámara libre se ha desactivado porque has recibido daño");
toggle();
}
@@ -324,22 +324,22 @@ public class Freecam extends Module {
@SubscribeEvent
public void onBreakBlock(BreakBlockEvent event) {
if (cancelActionPackets.isEnabled()) event.cancel();
if (cancelActionPackets.getValue()) event.cancel();
}
@SubscribeEvent
public void onPlaceBlock(PlaceBlockEvent event) {
if (cancelActionPackets.isEnabled()) event.cancel();
if (cancelActionPackets.getValue()) event.cancel();
}
@SubscribeEvent
public void onInteractEntity(InteractEntityEvent event) {
if (cancelActionPackets.isEnabled()) event.cancel();
if (cancelActionPackets.getValue()) event.cancel();
}
@SubscribeEvent
public void onAttack(AttackEntityEvent event) {
if (cancelActionPackets.isEnabled()) event.cancel();
if (cancelActionPackets.getValue()) event.cancel();
}
public void changeLookDirection(double deltaX, double deltaY) {
@@ -39,7 +39,7 @@ public class Freelook extends Module {
keyMode.setValue(KeyModes.HOLD);
notify.setDefaultValue(false);
notify.setEnabled(false);
notify.setValue(false);
}
@Override
@@ -57,7 +57,7 @@ public class PerspectivePlus extends Module {
if (mc.options.getPerspective() == net.minecraft.client.option.Perspective.FIRST_PERSON
|| mc.currentScreen != null || scrollSens.getValue() <= 0) return;
if (KeyUtil.isKeyDown(scrollKey.getKey())) {
if (KeyUtil.isKeyDown(scrollKey.getValue())) {
distance -= event.getVertical() / 4 * (scrollSens.getValue() * distance);
event.cancel();
}
@@ -29,14 +29,14 @@ public class Rotations extends Module {
mc.player.setYaw(yaw.getFloatValue());
mc.player.setPitch(pitch.getFloatValue());
if (serverSide.isEnabled())
if (serverSide.getValue())
mc.player.networkHandler.sendPacket(new PlayerMoveC2SPacket.LookAndOnGround(
yaw.getFloatValue(), pitch.getFloatValue(), mc.player.isOnGround(), mc.player.horizontalCollision));
}
@SubscribeEvent
public void onChangeRotation(ChangeRotationEvent event) {
if (smooth.isEnabled()
if (smooth.getValue()
&& (event.getYaw() != yaw.getFloatValue() || event.getPitch() != pitch.getFloatValue())){
event.cancel();
}}
@@ -50,7 +50,7 @@ public class Zoom extends Module {
keyMode.setValue(KeyModes.HOLD);
notify.setDefaultValue(false);
notify.setEnabled(false);
notify.setValue(false);
}
@Override
@@ -61,7 +61,7 @@ public class Zoom extends Module {
prevMouseSens = mc.options.getMouseSensitivity().getValue();
prevFov = mc.options.getFov().getValue();
prevHUD = mc.options.hudHidden;
mc.options.hudHidden = !showHUD.isEnabled();
mc.options.hudHidden = !showHUD.getValue();
value = defaultZoom.getValue();
@@ -83,14 +83,14 @@ public class Zoom extends Module {
@Override
public void onTick() {
mc.options.smoothCameraEnabled = smoothCam.isEnabled();
if (!smoothCam.isEnabled())
mc.options.smoothCameraEnabled = smoothCam.getValue();
if (!smoothCam.getValue())
mc.options.getMouseSensitivity().setValue(prevMouseSens * mouseSensMultiplier.getValue());
}
@SubscribeEvent
private void onMouseScroll(MouseScrollEvent event) {
boolean key = scrollKey.getKey() == GLFW.GLFW_KEY_UNKNOWN || KeyUtil.isKeyDown(scrollKey.getKey());
boolean key = scrollKey.getValue() == GLFW.GLFW_KEY_UNKNOWN || KeyUtil.isKeyDown(scrollKey.getValue());
if (isEnabled() && scrollSens.getValue() > 0 && key) {
value += event.getVertical() * 0.25 * (scrollSens.getValue() * value);
if (value < 1) value = 1;
@@ -0,0 +1,235 @@
package me.retucio.sputnik.module.modules.client;
import dev.firstdark.rpc.DiscordRpc;
import dev.firstdark.rpc.enums.ActivityType;
import dev.firstdark.rpc.enums.ErrorCode;
import dev.firstdark.rpc.exceptions.UnsupportedOsType;
import dev.firstdark.rpc.handlers.RPCEventHandler;
import dev.firstdark.rpc.models.DiscordRichPresence;
import dev.firstdark.rpc.models.User;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.Setting;
import me.retucio.sputnik.module.setting.SettingGroup;
import me.retucio.sputnik.module.setting.settings.EnumSetting;
import me.retucio.sputnik.module.setting.settings.StringSetting;
import me.retucio.sputnik.util.ChatUtil;
public class DiscordRPC extends Module {
SettingGroup sgImage = addSg(new SettingGroup("imágenes", false));
SettingGroup sgButton = addSg(new SettingGroup("botón", false));
// general
public StringSetting details = sgGeneral.add(new StringSetting(
"detalles", "título",
"usando el mod de putas de retucio",
40
));
public StringSetting state = sgGeneral.add(new StringSetting(
"estado", "subtítulo",
"(se lo está pasando en grande)",
40
));
public StringSetting startTimestamp = sgGeneral.add(new StringSetting(
"sello de tiempo", "sello de tiempo del comienzo de la actividad, siguiendo el unix epoch (dejar vacío para ahora)",
"",
20
));
public EnumSetting<ActivityTypes> activityType = sgGeneral.add(new EnumSetting<>(
"tipo de actividad", "qué tipo de actividad se está llevando a cabo",
ActivityTypes.class, ActivityTypes.PLAYING
));
public StringSetting appId = sgGeneral.add(new StringSetting(
"id del bot", "id del bot a usar (obtener de discord.dev)",
"1314254766150258729", 20
));
// imágenes
public StringSetting largeImageKey = sgImage.add(new StringSetting(
"imagen grande", "clave de la imagen grande",
"pengiun",
40
));
public StringSetting largeImageText = sgImage.add(new StringSetting(
"texto de la imagen grande", "texto mostrado junto a la imagen grande",
"pengüino",
40
));
public StringSetting smallImageKey = sgImage.add(new StringSetting(
"imagen pequeña", "clave de la imagen pequeña",
"pengiun",
40
));
public StringSetting smallImageText = sgImage.add(new StringSetting(
"texto de la imagen pequeña", "texto mostrado junto a la imagen pequeña",
"pengüino",
40
));
// botón
public StringSetting buttonText = sgButton.add(new StringSetting(
"texto del botón", "texto a mostrar en el botón",
"hola",
20
));
public StringSetting buttonUrl = sgButton.add(new StringSetting(
"url del botón", "rickroll en gran 26 :wilted_rose:",
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
20
));
// crear el rpc
private boolean initialized;
DiscordRpc rpc = new DiscordRpc();
RPCEventHandler handler = new RPCEventHandler() {
@Override
public void ready(User user) {
rpc.updatePresence(getPresence());
}
@Override
public void disconnected(ErrorCode errorCode, String message) {
ChatUtil.warn("desconectado: " + errorCode + " - " + message);
toggle();
}
@Override
public void errored(ErrorCode errorCode, String message) {
ChatUtil.error("error: " + errorCode + " - " + message);
toggle();
}
};
public DiscordRPC() {
super("discordRPC",
"personaliza la actividad de tu perfil en dishkor",
Category.CLIENT);
rpc.setDebugMode(false);
for (Setting<?> s : getSettings()) {
s.onUpdate(v -> update());
}
appId.onUpdate(v -> reload());
}
@Override
public void onEnable() {
String token = appId.getValue();
if (token == null || token.trim().isEmpty()) {
ChatUtil.error("configura el token del bot primero");
toggle();
return;
}
try {
rpc.init(token, handler, false);
initialized = true;
} catch (UnsupportedOsType e) {
ChatUtil.error("sistema operativo no soportado");
toggle();
} catch (Exception e) {
ChatUtil.error("error al inicializar rpc: " + e.getMessage());
toggle();
}
super.onEnable();
}
@Override
public void onDisable() {
if (initialized) {
rpc.shutdown();
initialized = false;
}
super.onDisable();
}
private DiscordRichPresence getPresence() {
return DiscordRichPresence.builder()
.details(details.getValue())
.state(state.getValue())
.largeImageKey(largeImageKey.getValue())
.largeImageText(largeImageText.getValue())
.smallImageKey(smallImageKey.getValue())
.smallImageText(smallImageText.getValue())
.startTimestamp(getTimestamp())
.activityType(activityType.getValue().getActivityType())
.button(DiscordRichPresence.RPCButton.of(
buttonText.getValue(),
buttonUrl.getValue())
).build();
}
private void update() {
if (initialized && isEnabled()) {
try {
rpc.updatePresence(getPresence());
} catch (Exception e) {
ChatUtil.error("error al actualizar rpc: " + e.getMessage());
}
}
}
public void reload() {
if (initialized && isEnabled()) {
rpc.shutdown();
try {
rpc.init(appId.getValue(), handler, false);
} catch (UnsupportedOsType e) {
ChatUtil.error(e.getMessage());
}
}
}
private long getTimestamp() {
long timestamp;
if (startTimestamp.getValue().trim().isEmpty()) {
timestamp = System.currentTimeMillis();
} else {
try {
timestamp = Long.parseLong(startTimestamp.getValue());
} catch (NumberFormatException e) {
ChatUtil.error("introduce un NÚMERO (o déjalo vacío)");
timestamp = System.currentTimeMillis();
}
}
return timestamp / 1000;
}
public enum ActivityTypes {
PLAYING("jugando"),
STREAMING("streameando"),
LISTENING("escuchando"),
WATCHING("viendo"),
CUSTOM("custom"),
COMPETING("compitiendo");
private final String name;
ActivityTypes(String name) { this.name = name; }
@Override public String toString() { return name; }
private ActivityType getActivityType() { return ActivityType.values()[ordinal()]; }
}
}
@@ -1,5 +1,6 @@
package me.retucio.sputnik.module.modules.client;
import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.command.CommandManager;
import me.retucio.sputnik.event.SubscribeEvent;
import me.retucio.sputnik.event.events.TickEvent;
@@ -28,25 +29,76 @@ public class GUI extends Module {
SettingGroup sgChat = addSg(new SettingGroup("chat", true));
SettingGroup sgMisc = addSg(new SettingGroup("misc.", true));
public ColorSetting color = sgGeneral.add(new ColorSetting("color", "color principal de la interfaz y el mod",
new Color(70, 20, 210, 230), false));
public ColorSetting color = sgGeneral.add(new ColorSetting(
"color",
"color principal de la interfaz y el mod",
new Color(70, 20, 210, 230),
false
));
// números negativos para deslizamiento inverso, 0 para desactivar
public NumberSetting scrollSens = sgWidgets.add(new NumberSetting("sensibilidad del scroll", "qué tan sensible es la interfaz a la rueda del ratón",
5, -15, 15, 0.5));
public BooleanSetting scrollBar = sgWidgets.add(new BooleanSetting("barra de desplazamiento", "renderizar una barra de desplazamiento a la derecha de la interfaz", true));
public NumberSetting scrollSens = sgWidgets.add(new NumberSetting(
"sensibilidad del scroll",
"qué tan sensible es la interfaz a la rueda del ratón",
5,
-15,
15,
0.5
));
public BooleanSetting scrollBar = sgWidgets.add(new BooleanSetting(
"barra de desplazamiento",
"renderizar una barra de desplazamiento a la derecha de la interfaz",
true
));
public BooleanSetting searchBar = sgWidgets.add(new BooleanSetting("barra de búsqueda", "renderizar una barra de búsqueda que filtra resultados en todos los marcos abiertos", true));
public BooleanSetting matchCase = sgWidgets.add(new BooleanSetting("distinguir mayúsculas", "la búsqueda es sensible a mayúsculas y minúsculas", false));
public BooleanSetting searchBar = sgWidgets.add(new BooleanSetting(
"barra de búsqueda",
"renderizar una barra de búsqueda que filtra resultados en todos los marcos abiertos",
true
));
public BooleanSetting matchCase = sgWidgets.add(new BooleanSetting(
"distinguir mayúsculas",
"la búsqueda es sensible a mayúsculas y minúsculas",
false
));
// ^^^ no sé de qué sirve porque está todo en minúsculas pero bueno
public BooleanSetting blur = sgUi.add(new BooleanSetting("desenfoque", "desenfocar el fondo mientras la interfaz está abierta", true));
public StringSetting watermark = sgUi.add(new StringSetting("marca de agua", "marca de agua para interfaces (dejar vacío para desactivar)", me.retucio.sputnik.Sputnik.getVersionName(), 40));
public BooleanSetting blur = sgUi.add(new BooleanSetting(
"desenfoque",
"desenfocar el fondo mientras la interfaz está abierta",
true
));
public StringSetting watermark = sgUi.add(new StringSetting(
"marca de agua",
"marca de agua para interfaces (dejar vacío para desactivar)",
Sputnik.getVersionName(),
40
));
public StringSetting commandPrefix = sgChat.add(new StringSetting("prefijo", "prefijo de los comandos", "$", 10));
public StringSetting chatName = sgChat.add(new StringSetting("nombre", "qué nombre usar en notificaciones por el chat", "smegma", 20));
public StringSetting commandPrefix = sgChat.add(new StringSetting(
"prefijo",
"prefijo de los comandos",
"$",
10
));
public StringSetting chatName = sgChat.add(new StringSetting(
"nombre",
"qué nombre usar en notificaciones por el chat",
"smegma",
20
));
public BooleanSetting multipleKeybinds = sgMisc.add(new BooleanSetting("teclas multimódulo", "permitir asignar la misma tecla a más de un módulo", false));
public BooleanSetting multipleKeybinds = sgMisc.add(new BooleanSetting(
"teclas multimódulo",
"permitir asignar la misma tecla a más de un módulo o acción",
false
));
public StringSetting windowTitle = sgMisc.add(new StringSetting(
"título",
"título de la ventana",
Sputnik.getVersionName(),
50
));
public GUI() {
super("interfaz",
@@ -25,21 +25,92 @@ public class HUD extends Module {
SettingGroup sgElements = addSg(new SettingGroup("elementos", false));
// editor
public KeySetting editorKey = sgEditor.add(new KeySetting("tecla del editor", "tecla asignada al editor de elementos del hud", GLFW.GLFW_KEY_PAGE_UP));
public KeySetting editorKey = sgEditor.add(new KeySetting(
"tecla del editor",
"tecla asignada al editor de elementos del hud",
GLFW.GLFW_KEY_PAGE_UP
));
public BooleanSetting axialMovement = sgEditor.add(new BooleanSetting(
"movimiento axial",
"te permite mover los elementos sobre los ejes más fácilmente",
true
));
public NumberSetting axisOffset = sgEditor.add(new NumberSetting(
"offset de los ejes",
"offset a tener en cuenta al usar el movimiento axial",
10,
0,
50,
1
));
public BooleanSetting arrowMovement = sgEditor.add(new BooleanSetting(
"movimiento con flechas",
"te permite mover el elemento seleccionado con las teclas de las flechas",
true
));
public NumberSetting arrowOffset = sgEditor.add(new NumberSetting(
"cuánto mover con las flechas",
"cuántos píxeles mover el elemento seleccionado al usar las flechas",
2,
1,
20,
1
));
// ajustes
public ColorSetting color = sgDisplay.add(new ColorSetting("color", "color del texto de los elementos del HUD",
new Color(255, 255, 255, 255), false));
public BooleanSetting shadow = sgDisplay.add(new BooleanSetting("sombra", "texto con sombra", true));
public BooleanSetting showOnF3 = sgDisplay.add(new BooleanSetting("mostrar en F3", "renderizar HUD en el menú de debug", false));
public BooleanSetting showOnChat = sgDisplay.add(new BooleanSetting("mostrar en chat", "renderizar HUD en la pantalla del chat", false));
// renderizado
public ColorSetting color = sgDisplay.add(new ColorSetting(
"color",
"color del texto de los elementos del HUD",
new Color(255, 255, 255, 255), false)
);
public BooleanSetting shadow = sgDisplay.add(new BooleanSetting(
"sombra",
"texto con sombra",
true
));
public BooleanSetting showOnF3 = sgDisplay.add(new BooleanSetting(
"mostrar en F3",
"renderizar HUD en el menú de debug",
false
));
public BooleanSetting showOnChat = sgDisplay.add(new BooleanSetting(
"mostrar en chat",
"renderizar HUD en la pantalla del chat",
false
));
public NumberSetting timezone = sgElements.add(new NumberSetting("zona horaria", "zona horaria en UTC+n", 1, -6, 6, 1));
public EnumSetting<TimeFormat> timeFormat = sgElements.add(new EnumSetting<>("formato de la hora", "12h o 24h", TimeFormat.class, TimeFormat.TWENTY_FOUR_HOUR));
public StringSetting customText = sgElements.add(new StringSetting("texto custom", "marca de agua (dejar vacío para quitar)", "adolf jitler inshtagram feishbuc twiter", 40));
public EnumSetting<CoordsMode> coordsMode = sgElements.add(new EnumSetting<>("modo de coordenadas", "qué coordenadas mostrar", CoordsMode.class, CoordsMode.OVERWORLD));
public EnumSetting<Dynosaurs> dyno = sgElements.add(new EnumSetting<>("dinosaurio", "qué dinosaurio mostrar",
Dynosaurs.class, Dynosaurs.SPINOSAURUS));
// elementos
public NumberSetting timezone = sgElements.add(new NumberSetting(
"zona horaria",
"zona horaria en UTC+n",
1,
-6,
6,
1
));
public EnumSetting<TimeFormat> timeFormat = sgElements.add(new EnumSetting<>(
"formato de la hora",
"12h o 24h",
TimeFormat.class,
TimeFormat.TWENTY_FOUR_HOUR
));
public StringSetting customText = sgElements.add(new StringSetting(
"texto custom",
"marca de agua (dejar vacío para quitar)",
"adolf jitler inshtagram feishbuc twiter",
40
));
public EnumSetting<CoordsMode> coordsMode = sgElements.add(new EnumSetting<>(
"modo de coordenadas",
"qué coordenadas mostrar",
CoordsMode.class,
CoordsMode.OVERWORLD
));
public EnumSetting<Dynosaurs> dyno = sgElements.add(new EnumSetting<>(
"dinosaurio",
"qué dinosaurio mostrar",
Dynosaurs.class, Dynosaurs.SPINOSAURUS
));
public HUD() {
super("HUD",
@@ -48,6 +119,9 @@ public class HUD extends Module {
GLFW.GLFW_KEY_F12
);
axialMovement.onUpdate(v -> axisOffset.setVisible(v));
arrowMovement.onUpdate(v -> arrowOffset.setVisible(v));
dyno.onUpdate(v -> {
DynoElement element = (DynoElement) HudRenderer.getElement(DynoElement.class);
if (element != null) element.reloadTexture();
@@ -15,10 +15,25 @@ import java.util.WeakHashMap;
public class BossbarStack extends Module {
public BooleanSetting stackBars = sgGeneral.add(new BooleanSetting("apilar barras", "apilar las bossbars", true));
public BooleanSetting hideNames = sgGeneral.add(new BooleanSetting("esconder nombres", "no renderiza el nombre de los bosses", false));
public NumberSetting spaceReduction = sgGeneral.add(new NumberSetting("reducción de espacio", "cuánto reducir el espacio entre bossbars",
0, 0, 10, 0.1));
public BooleanSetting stackBars = sgGeneral.add(new BooleanSetting(
"apilar barras", "apilar las bossbars",
true
));
public BooleanSetting hideNames = sgGeneral.add(new BooleanSetting(
"esconder nombres", "no renderiza el nombre de los bosses",
false
));
public NumberSetting spaceReduction = sgGeneral.add(new NumberSetting(
"reducción de espacio",
"cuánto reducir el espacio entre bossbars",
0,
0,
10,
0.1
));
private final Map<ClientBossBar, Integer> bossBarMap = new WeakHashMap<>();
@@ -30,16 +45,16 @@ public class BossbarStack extends Module {
@SubscribeEvent
private void onRenderBossText(RenderBossbarEvent.BossText event) {
if (hideNames.isEnabled()) {
if (hideNames.getValue()) {
event.setName(Text.empty());
return;
} else if (bossBarMap.isEmpty() || !stackBars.isEnabled()) return;
} else if (bossBarMap.isEmpty() || !stackBars.getValue()) return;
ClientBossBar bar = event.getBossBar();
Integer amount = bossBarMap.get(bar);
bossBarMap.remove(bar);
if (amount != null && !hideNames.isEnabled())
if (amount != null && !hideNames.getValue())
event.setName(event.getName().copy().append(" x" + amount));
}
@@ -50,7 +65,7 @@ public class BossbarStack extends Module {
@SubscribeEvent
private void onRenderBossBars(RenderBossbarEvent.BossIterator event) {
if (stackBars.isEnabled()) {
if (stackBars.getValue()) {
HashMap<String, ClientBossBar> chosenBarMap = new HashMap<>();
event.getIterator().forEachRemaining(bar -> {
String name = bar.getName().getString();
@@ -82,7 +82,7 @@ public class ChatPlus extends Module {
Text message = event.getMessage();
// registrar mensajes para evitar su eliminación
if (logger.isEnabled()) {
if (logger.getValue()) {
String messageString = message.getString();
if (loggerRegex.matcher(messageString).find()) {
MutableText newMessage = Text.empty();
@@ -100,7 +100,7 @@ public class ChatPlus extends Module {
}
// agregar sellos de tiempo a los mensajes
if (timestamps.isEnabled()) {
if (timestamps.getValue()) {
Text timestamp = Text.literal("[" + dateFormat.format(new Date()) + "] ").formatted(Formatting.GRAY);
message = Text.empty().append(timestamp).append(message);
}
@@ -112,7 +112,7 @@ public class ChatPlus extends Module {
@SubscribeEvent
private void onSendMessage(SendMessageEvent event) {
// evitar mandar coordenadas por el chat
if (coordsProtection.isEnabled() && containsCoordinates(event.getMessage())) {
if (coordsProtection.getValue() && containsCoordinates(event.getMessage())) {
ChatUtil.warn(Text.literal("cuidadito con las coordenadas chavalín").append(
getSendButton(event.getMessage())));
@@ -127,7 +127,7 @@ public class ChatPlus extends Module {
@SuppressWarnings("DataFlowIssue")
public void beforeDrawMessage(DrawContext context, ChatHudLine.Visible line, int y, int color) {
if (!isEnabled() || !showHeads.isEnabled()) return;
if (!isEnabled() || !showHeads.getValue()) return;
// dibujar la cabeza al principio del mensaje
if (((IChatHudLineVisible) (Object) line).sputnik$isStartOfEntry())
@@ -139,7 +139,7 @@ public class ChatPlus extends Module {
public void afterDrawMessage(DrawContext context) {
// finalizar renderizado de la cabeza
if (!isEnabled() || !showHeads.isEnabled()) return;
if (!isEnabled() || !showHeads.getValue()) return;
context.getMatrices().popMatrix();
}
@@ -218,7 +218,7 @@ public class ChatPlus extends Module {
}
private void updateDateFormat() {
dateFormat = new SimpleDateFormat(timestampSecs.isEnabled() ? "HH:mm:ss" : "HH:mm");
dateFormat = new SimpleDateFormat(timestampSecs.getValue() ? "HH:mm:ss" : "HH:mm");
}
private boolean containsCoordinates(String message) {
@@ -52,10 +52,10 @@ public class ScreenshotPlus extends Module {
public void sendScreenshotMessage() {
MutableText baseText = Text.literal("captura de pantalla tomada\n");
if (saveButton.isEnabled() && !defaultAction.is(ScreenshotActions.SAVE)) baseText.append(getSaveButton().append(" "));
if (copyButton.isEnabled()) baseText.append(getCopyButton().append(" "));
if (openButton.isEnabled() && defaultAction.is(ScreenshotActions.SAVE)) baseText.append(getOpenButton().append(" "));
if (discardButton.isEnabled() && !defaultAction.is(ScreenshotActions.NONE)) baseText.append(getDiscardButton().append(" "));
if (saveButton.getValue() && !defaultAction.is(ScreenshotActions.SAVE)) baseText.append(getSaveButton().append(" "));
if (copyButton.getValue()) baseText.append(getCopyButton().append(" "));
if (openButton.getValue() && defaultAction.is(ScreenshotActions.SAVE)) baseText.append(getOpenButton().append(" "));
if (discardButton.getValue() && !defaultAction.is(ScreenshotActions.NONE)) baseText.append(getDiscardButton().append(" "));
ChatUtil.info(baseText);
}
@@ -62,7 +62,7 @@ public class ShulkerPeek extends Module {
@SubscribeEvent
public void onKey(KeyEvent event) {
if (mc.player == null) return;
if (event.getKey() != previewKey.getKey()) return;
if (event.getKey() != previewKey.getValue()) return;
if (event.getAction() == GLFW.GLFW_PRESS) {
openPreviewScreen();
@@ -0,0 +1,11 @@
package me.retucio.sputnik.module.modules.misc;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
public class UnfocusedCpu extends Module {
public UnfocusedCpu() {
super("aliviar cpu", "evita renderizar objetos en pantalla si la ventana no está seleccionada", Category.MISC);
}
}
@@ -0,0 +1,91 @@
package me.retucio.sputnik.module.modules.movement;
import com.google.common.eventbus.Subscribe;
import me.retucio.sputnik.event.BoatMoveEvent;
import me.retucio.sputnik.event.SubscribeEvent;
import me.retucio.sputnik.event.events.PacketEvent;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.BooleanSetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting;
import net.minecraft.network.packet.s2c.play.VehicleMoveS2CPacket;
import net.minecraft.util.math.Vec3d;
public class BoatFly extends Module {
public NumberSetting speed = sgGeneral.add(new NumberSetting(
"velocidad horizontal",
"velocidad a la que moverse horizontalmente",
2,
0,
5,
0.1
));
public NumberSetting vSpeed = sgGeneral.add(new NumberSetting(
"velocidad vertical",
"velocidad a la que moverse verticalmente",
1,
0,
5,
0.1
));
public NumberSetting stepHeight = sgGeneral.add(new NumberSetting(
"altura de escalonado",
"como escalones pero pal barco",
0.5,
0,
1,
0.1
));
public BooleanSetting cancelPackets = sgGeneral.add(new BooleanSetting(
"cancelar paquetes",
"cancelar paquetes de movimiento del barco enviados por el servidor",
false
));
public BoatFly() {
super("barco volador", "convierte tu bote de acacia en un Lockheed F-117 Nighthawk", Category.MOVEMENT);
}
@SubscribeEvent
private void onBoatMove(BoatMoveEvent event) {
if (event.getBoat().getControllingPassenger() != mc.player) return;
event.getBoat().setYaw(mc.player.getYaw());
float yaw = event.getBoat().getYaw();
int dx = 0, dy = 0, dz = 0;
if (mc.options.rightKey.isPressed()) dx++;
if (mc.options.leftKey.isPressed()) dx--;
if (mc.options.jumpKey.isPressed()) dy++;
if (mc.options.sprintKey.isPressed()) dy--;
// ctrl para bajar, en vez de shift, porque si no te desmontas
if (mc.options.backKey.isPressed()) dz++;
if (mc.options.forwardKey.isPressed()) dz--;
double speed = this.speed.getValue();
double sin = Math.sin(Math.toRadians(yaw));
double cos = Math.cos(Math.toRadians(yaw));
double x = speed * dz * sin;
double y = speed * dy;
double z = speed * dz * -cos;
x += speed * dx * -cos;
z += speed * dx * -sin;
event.getBoat().setVelocity(new Vec3d(x, y, z));
}
@Subscribe
private void onReceivePacket(PacketEvent.Receive event) {
if (event.getPacket() instanceof VehicleMoveS2CPacket && cancelPackets.getValue()) {
event.cancel();
}
}
}
@@ -0,0 +1,20 @@
package me.retucio.sputnik.module.modules.movement;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
public class Dolphin extends Module {
public Dolphin() {
super("delfín", "*ruido de delfín*", Category.MOVEMENT);
}
@Override
public void onTick() {
if (mc.player == null) return;
if (mc.player.isSubmergedInWater()) {
if (!mc.player.isJumping()) mc.player.jump();
}
}
}
@@ -1,4 +1,4 @@
package me.retucio.sputnik.module.modules.player;
package me.retucio.sputnik.module.modules.movement;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
@@ -13,7 +13,7 @@ import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket;
public class ElytraBounce extends Module {
public ElytraBounce() {
super("conejo", "haz el elytra-bounce manteniendo el espacio", Category.PLAYER);
super("conejo", "haz el elytra-bounce manteniendo el espacio", Category.MOVEMENT);
}
public boolean bounce() {
@@ -0,0 +1,61 @@
package me.retucio.sputnik.module.modules.movement;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.NumberSetting;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.util.math.Vec3d;
public class ElytraFly extends Module {
public NumberSetting speed = sgGeneral.add(new NumberSetting(
"velocidad",
"mi madre es parcialmente vagabunda",
1,
0,
5,
0.1
));
public ElytraFly() {
super("elytras", "vuela con elytras", Category.MOVEMENT);
}
@Override
public void onTick() {
if (mc.player == null || !mc.player.isGliding() || !wearingElytra()) return;
float yaw = mc.player.getYaw();
int dx = 0, dy = 0, dz = 0;
if (mc.options.rightKey.isPressed()) dx++;
if (mc.options.leftKey.isPressed()) dx--;
if (mc.options.jumpKey.isPressed()) dy++;
if (mc.options.sneakKey.isPressed()) dy--;
if (mc.options.backKey.isPressed()) dz++;
if (mc.options.forwardKey.isPressed()) dz--;
double speed = this.speed.getValue();
double sin = Math.sin(Math.toRadians(yaw));
double cos = Math.cos(Math.toRadians(yaw));
double x = speed * dz * sin;
double y = speed * dy;
double z = speed * dz * -cos;
x += speed * dx * -cos;
z += speed * dx * -sin;
mc.player.setVelocity(new Vec3d(x, y, z));
}
private boolean wearingElytra() {
ItemStack equippedStack = mc.player.getEquippedStack(EquipmentSlot.CHEST);
return equippedStack != null && equippedStack.getItem() == Items.ELYTRA;
}
}
@@ -1,4 +1,4 @@
package me.retucio.sputnik.module.modules.player;
package me.retucio.sputnik.module.modules.movement;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
@@ -11,7 +11,7 @@ public class Headhitters extends Module {
public Headhitters() {
super("headhitters",
"mantén pulsado el espacio para hacer headhitting sin tener que espamearlo",
Category.PLAYER);
Category.MOVEMENT);
}
@Override
@@ -0,0 +1,133 @@
package me.retucio.sputnik.module.modules.movement;
import me.retucio.sputnik.event.SubscribeEvent;
import me.retucio.sputnik.event.events.UseItemEvent;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.NumberSetting;
import net.minecraft.item.Items;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
// "pedido prestado" de: https://github.com/meanwhile131/elytra-infinite
public class InfiniteElytra extends Module {
private FlyState state;
private float pitch;
private double lowestY;
public NumberSetting pitchDown = sgGeneral.add(new NumberSetting(
"cabeceo (abajo)",
"cabeceo al ir hacia abajo",
30,
-90,
90,
1
));
public NumberSetting pitchUp = sgGeneral.add(new NumberSetting(
"cabeceo (arriba)",
"cabeceo al ir hacia arriba",
-48,
-90,
90,
1
));
public NumberSetting pitchDownSpeed = sgGeneral.add(new NumberSetting(
"velocidad de cabeceo (abajo)",
"velocidad del cabeceo al ir hacia abajo",
0.5,
0.01,
5,
0.1
));
public NumberSetting pitchUpVelocity = sgGeneral.add(new NumberSetting(
"velocidad de cabeceo (arriba)",
"velocidad del cabeceo al ir hacia arriba",
2,
0.01,
5,
0.1
));
public NumberSetting ticksCollisionLookAhead = sgGeneral.add(new NumberSetting(
"precaución de colisión",
"precaución de colisión en ticks",
10,
0,
20,
1
));
public InfiniteElytra() {
super("avioneta",
"vuela infinitamente, aprovechándose el sistema defectuoso que hizo mojang (hace falta tirarse de unos 50 bloques de altura)",
Category.MOVEMENT);
}
@Override
public void onTick() {
if (mc.player == null || mc.world == null || !mc.player.isGliding()) {
state = FlyState.NOT_FLYING;
return;
}
if (state == FlyState.NOT_FLYING) {
state = FlyState.GLIDING_DOWN;
pitch = pitchDown.getFloatValue();
} else if (state == FlyState.PITCHING_DOWN) {
pitch += Math.min(pitchDown.getFloatValue() - pitch, pitchDownSpeed.getFloatValue());
boolean movingDownwards = mc.player.getVelocity().y <= 0 && mc.player.getY() > lowestY;
if (pitch >= pitchDown.getFloatValue() || movingDownwards) {
pitch = pitchDown.getFloatValue();
state = FlyState.GLIDING_DOWN;
}
} else if (state == FlyState.GLIDING_DOWN) {
boolean willCollide = willCollideWhileGliding(ticksCollisionLookAhead.getIntValue());
if (willCollide || mc.player.getVelocity().horizontalLengthSquared() > Math.pow(pitchUpVelocity.getFloatValue(), 2)) {
pitch = pitchUp.getFloatValue();
state = FlyState.PITCHING_DOWN;
lowestY = mc.player.getY();
}
}
mc.player.setPitch(pitch);
}
@SubscribeEvent
public void onUseItem(UseItemEvent event) {
if (mc.player == null) return;
if (mc.player.getStackInHand(event.getHand()).getItem() == Items.FIREWORK_ROCKET && !mc.player.isSpectator() && mc.player.isGliding()) {
pitch = pitchUp.getFloatValue();
mc.player.setPitch(pitch);
state = FlyState.PITCHING_DOWN;
lowestY = mc.player.getY();
}
}
private boolean willCollideWhileGliding(int ticks) {
Vec3d velocity = mc.player.getVelocity();
Box boundingBox = mc.player.getBoundingBox();
for (int i = 0; i < ticks; i++) {
velocity = mc.player.calcGlidingVelocity(velocity);
boundingBox = boundingBox.offset(velocity);
if (!mc.world.isSpaceEmpty(null, boundingBox, true)) {
return true;
}
}
return false;
}
public enum FlyState {
NOT_FLYING,
GLIDING_DOWN,
PITCHING_DOWN;
}
}
@@ -0,0 +1,133 @@
package me.retucio.sputnik.module.modules.movement;
import me.retucio.sputnik.event.SubscribeEvent;
import me.retucio.sputnik.event.events.BlockShapeEvent;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.SettingGroup;
import me.retucio.sputnik.module.setting.settings.BooleanSetting;
import me.retucio.sputnik.module.setting.settings.EnumSetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting;
import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.fluid.FluidState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShapes;
public class Jesus extends Module {
SettingGroup sgBlocks = addSg(new SettingGroup("bloques", true));
public EnumSetting<JesusMode> mode = sgGeneral.add(new EnumSetting<>(
"modo",
"cómo caminar",
JesusMode.class,
JesusMode.SOLID
));
public BooleanSetting allowSneaking = sgGeneral.add(new BooleanSetting(
"permitir agacharse",
"te permite usar el botón de agacharse para sumergirte en el agua",
true
));
public NumberSetting minFallHeight = sgGeneral.add(new NumberSetting(
"distancia de caída",
"distancia de caída mínima para sumergirse en vez de impactar",
3,
0.1,
10,
0.1
));
public BooleanSetting water = sgBlocks.add(new BooleanSetting(
"agua",
"permitir caminar en agua",
true
));
public BooleanSetting lava = sgBlocks.add(new BooleanSetting(
"lava",
"permitir caminar en lava",
true
));
public BooleanSetting powderedSnow = sgBlocks.add(new BooleanSetting(
"nieve en polvo",
"permitir caminar en nieve en polvo",
true
));
public Jesus() {
super("jesús", "te permite caminar sobre el agua", Category.MOVEMENT);
}
@Override
public void onTick() {
if (mc.player == null || mc.world == null) return;
Entity entity = mc.player.getRootVehicle();
if (entity.isSneaking() && allowSneaking.getValue()) {
return;
}
if (entity.fallDistance >= minFallHeight.getValue()) {
return;
}
if (!mode.is(JesusMode.VIBRATE)) return;
if (isSubmerged(entity.getEntityPos().add(new Vec3d(0, 0.3, 0)))) {
entity.setVelocity(entity.getVelocity().x, 0.08, entity.getVelocity().z);
}
else if (isSubmerged(entity.getEntityPos().add(new Vec3d(0, 0.1, 0)))) {
entity.setVelocity(entity.getVelocity().x, 0.05, entity.getVelocity().z);
}
else if (isSubmerged(entity.getEntityPos().add(new Vec3d(0, 0.05, 0)))) {
entity.setVelocity(entity.getVelocity().x, 0.01, entity.getVelocity().z);
}
else if (isSubmerged(entity.getEntityPos())) {
entity.setVelocity(entity.getVelocity().x, -0.005, entity.getVelocity().z);
entity.setOnGround(true);
}
}
@SubscribeEvent
public void onBlockShape(BlockShapeEvent event) {
if (event.getState().getBlock() == Blocks.LAVA && !lava.getValue()) return;
if (event.getState().getBlock() == Blocks.WATER && !water.getValue()) return;
if (event.getState().getBlock() == Blocks.POWDER_SNOW && !powderedSnow.getValue()) return;
if (mode.getValue() == JesusMode.SOLID)
if (event.getState().getBlock() == Blocks.POWDER_SNOW
&& !mc.player.isSneaking()
&& mc.player.getY() > event.getPos().getY() + 1) {
event.setShape(VoxelShapes.cuboid(0, 0, 0, 1, 1.01, 1));
} else if (!mc.world.getFluidState(event.getPos()).isEmpty()
&& !mc.player.isSneaking()
&& !mc.player.isTouchingWater()
&& mc.player.getY() >= event.getPos().getY() + 0.9) {
event.setShape(VoxelShapes.cuboid(0, 0, 0, 1, 0.9, 1));
}
}
private boolean isSubmerged(Vec3d pos) {
BlockPos blockPos = BlockPos.ofFloored(pos);
FluidState state = mc.world.getFluidState(blockPos);
return !state.isEmpty() && pos.y - blockPos.getY() <= state.getHeight();
}
public enum JesusMode {
VIBRATE("vibrador"),
SOLID("sólido");
private final String name;
JesusMode(String name) { this.name = name; }
@Override public String toString() { return name; }
}
}
@@ -0,0 +1,84 @@
package me.retucio.sputnik.module.modules.movement;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.BooleanSetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.RaycastContext;
public class ReverseStep extends Module {
public NumberSetting height = sgGeneral.add(new NumberSetting(
"altura", "altura máxima a bajar",
1, 0, 20, 0.1
));
public NumberSetting velocity = sgGeneral.add(new NumberSetting(
"velocidad", "velocidad a la que caer en bps",
1, 0, 10, 0.1
));
public BooleanSetting jumping = sgGeneral.add(new BooleanSetting(
"saltar", "permitir saltar",
true
));
public BooleanSetting disableInWater = sgGeneral.add(new BooleanSetting(
"desactivar en agua", ".",
true
));
public ReverseStep() {
super("escalones inversos",
"escalones pero pabajo",
Category.MOVEMENT
);
}
@Override
public void onTick() {
if (mc.player == null || mc.world == null) return;
if (!mc.player.isOnGround()) {
if (jumping.getValue()) return;
}
if ((mc.player.isTouchingWater() || mc.player.isInLava())) {
if (disableInWater.getValue()) return;
}
double dropHeight = getHeight();
if (dropHeight > 0 && dropHeight <= height.getValue()) {
mc.player.addVelocity(0, -height.getValue() + mc.player.getVelocity().getY(), 0);
}
}
private double getHeight() {
Vec3d start = new Vec3d(mc.player.getX(), mc.player.getY() - 0.1, mc.player.getZ());
Vec3d end = new Vec3d(mc.player.getX(), mc.player.getY() - height.getValue() - 1, mc.player.getZ());
RaycastContext context = new RaycastContext(
start, end,
RaycastContext.ShapeType.COLLIDER,
RaycastContext.FluidHandling.ANY,
mc.player
);
HitResult hit = mc.world.raycast(context);
if (hit != null && hit.getType() == HitResult.Type.BLOCK) {
BlockPos hitPos = new BlockPos(
(int) hit.getPos().x,
(int) hit.getPos().y,
(int) hit.getPos().z
);
return mc.player.getY() - (hitPos.getY());
}
return -1;
}
}
@@ -1,4 +1,4 @@
package me.retucio.sputnik.module.modules.player;
package me.retucio.sputnik.module.modules.movement;
import me.retucio.sputnik.event.SubscribeEvent;
import me.retucio.sputnik.event.events.ClipAtLedgeEvent;
@@ -18,7 +18,7 @@ public class SafeWalk extends Module {
public SafeWalk() {
super("muletas",
"te ayuda a no caerte de bloques, sin agacharte",
Category.PLAYER);
Category.MOVEMENT);
}
@SubscribeEvent
@@ -0,0 +1,45 @@
package me.retucio.sputnik.module.modules.movement;
import me.retucio.sputnik.mixin.accessor.AbstractBlockAccessor;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.NumberSetting;
import net.minecraft.block.Block;
import net.minecraft.util.math.Vec3i;
import java.util.HashMap;
import java.util.Map;
public class Slippy extends Module {
public NumberSetting slipperiness = sgGeneral.add(new NumberSetting(
"cantidad de semen",
"cuánto semen agregar a los bloques por los que pasas",
1,
0,
2,
0.01
));
private final Map<Block, Float> modifiedBlocks = new HashMap<>();
public Slippy() {
super("patinaje", "añade una fina capa de semen a los bloques que pisas", Category.MOVEMENT);
}
@Override
public void onDisable() {
for (Block block : modifiedBlocks.keySet()) {
((AbstractBlockAccessor) block).setSlipperiness(modifiedBlocks.get(block));
}
}
@Override
public void onTick() {
if (mc.player == null || mc.world == null) return;
Block block = mc.world.getBlockState(mc.player.getBlockPos().add(new Vec3i(0, -1, 0))).getBlock();
if (block.getSlipperiness() == slipperiness.getFloatValue()) return;
if (!modifiedBlocks.containsKey(block)) modifiedBlocks.put(block, block.getSlipperiness());
((AbstractBlockAccessor) block).setSlipperiness(slipperiness.getFloatValue());
}
}
@@ -0,0 +1,17 @@
package me.retucio.sputnik.module.modules.movement;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.NumberSetting;
public class Step extends Module {
public NumberSetting height = sgGeneral.add(new NumberSetting(
"altura", "altura máxima a subir",
1, 0, 3, 0.1
));
public Step() {
super("escalones", "hace que el bloque de subida de escalón sea la distancia deseada", Category.MOVEMENT);
}
}
@@ -0,0 +1,28 @@
package me.retucio.sputnik.module.modules.movement;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.BooleanSetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting;
public class TridentBoost extends Module {
public NumberSetting multiplier = sgGeneral.add(new NumberSetting(
"boost",
"multiplicador del movimiento",
2,
0,
5,
0.1
));
public BooleanSetting outOfWater = sgGeneral.add(new BooleanSetting(
"fuera del agua",
"permitir el uso de la propulsión acuática fuera del agua",
true
));
public TridentBoost() {
super("tenedor mágico", "hermano se piensa que es Poseidón", Category.MOVEMENT);
}
}
@@ -61,12 +61,12 @@ public class LogoutSpots extends Module {
outlines.onUpdate(v -> {
outlineColor.setVisible(v);
fullHeight.setVisible(v || filling.isEnabled());
fullHeight.setVisible(v || filling.getValue());
});
filling.onUpdate(v -> {
fillingColor.setVisible(v);
fullHeight.setVisible(v || outlines.isEnabled());
fullHeight.setVisible(v || outlines.getValue());
});
dummy.onUpdate(v -> {
@@ -116,7 +116,7 @@ public class LogoutSpots extends Module {
if (player.getUuid().equals(entry.getProfile().id())) {
LogoutEntry logoutEntry = new LogoutEntry(player);
if (mc.world != null && !mc.world.hasEntity(logoutEntry.dummy) && dummy.isEnabled())
if (mc.world != null && !mc.world.hasEntity(logoutEntry.dummy) && dummy.getValue())
mc.world.addEntity(logoutEntry.dummy);
addLogoutSpot(logoutEntry);
@@ -248,21 +248,21 @@ public class LogoutSpots extends Module {
}
public void renderBox(MatrixStack matrices) {
if (fullHeight.isEnabled()) {
if (outlines.isEnabled())
RenderUtil.drawOutlineBox(matrices, new Box(x, y, z, x + xWidth, y + height, z + zWidth), outlineColor.getColor(), lineWidth.getFloatValue(), true);
if (filling.isEnabled())
RenderUtil.drawFilledBox(matrices, new Box(x, y, z, x + xWidth, y + height, z + zWidth), fillingColor.getColor(), true);
if (fullHeight.getValue()) {
if (outlines.getValue())
RenderUtil.drawOutlineBox(matrices, new Box(x, y, z, x + xWidth, y + height, z + zWidth), outlineColor.getValue(), lineWidth.getFloatValue(), true);
if (filling.getValue())
RenderUtil.drawFilledBox(matrices, new Box(x, y, z, x + xWidth, y + height, z + zWidth), fillingColor.getValue(), true);
} else {
if (outlines.isEnabled()) {
if (outlines.getValue()) {
RenderUtil.drawBlockFaceOutlines(matrices,
BlockPos.ofFloored(x + halfWidth, y, z + halfWidth),
Direction.UP, outlineColor.getColor(), lineWidth.getFloatValue(), true);
Direction.UP, outlineColor.getValue(), lineWidth.getFloatValue(), true);
}
if (filling.isEnabled()) {
if (filling.getValue()) {
RenderUtil.drawBlockFaceFilled(matrices,
BlockPos.ofFloored(x + halfWidth, y, z + halfWidth),
Direction.UP, fillingColor.getColor(), 0.001f, true);
Direction.UP, fillingColor.getValue(), 0.001f, true);
}
}
}
@@ -0,0 +1,169 @@
package me.retucio.sputnik.module.modules.network;
import me.retucio.sputnik.event.SubscribeEvent;
import me.retucio.sputnik.event.events.AttackBlockEvent;
import me.retucio.sputnik.event.events.Render3DEvent;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.SettingGroup;
import me.retucio.sputnik.module.setting.settings.BooleanSetting;
import me.retucio.sputnik.module.setting.settings.ColorSetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting;
import me.retucio.sputnik.util.render.RenderUtil;
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import java.awt.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class PacketMine extends Module {
SettingGroup sgRender = addSg(new SettingGroup("renderizado", true));
public NumberSetting retryTime = sgGeneral.add(new NumberSetting(
"delay",
"delay entre reintentos de minado",
30,
0,
1000,
1
));
public BooleanSetting cancelOutOfReach = sgGeneral.add(new BooleanSetting(
"cancelar fuera de alcance",
"cancelar aquellos paquetes que intenten romper bloques fuera del alcance del jugador, para evitar flaggear el anticheat",
true
));
public BooleanSetting render = sgRender.add(new BooleanSetting(
"renderizar",
"renderizar un contorno alrededor de los bloques que están siendo minados",
true
));
public ColorSetting color = sgRender.add(new ColorSetting(
"color",
"color del contorno renderizado",
new Color(0, 255, 0, 100),
false
));
public NumberSetting lineWidth = sgRender.add(new NumberSetting(
"grosor",
"grosor de las líneas del contorno",
2,
0.1,
10,
0.1
));
public PacketMine() {
super("selección de minado",
"selecciona bloques a minar con paquetes",
Category.NETWORK);
render.onUpdate(v -> {
color.setVisible(v);
lineWidth.setVisible(v);
});
}
private final List<MiningBlock> miningBlocks = new ArrayList<>();
@Override
public void onDisable() {
miningBlocks.clear();
super.onDisable();
}
@Override
public void onTick() {
if (mc.player == null || mc.world == null || mc.interactionManager == null) return;
Iterator<MiningBlock> iterator = miningBlocks.iterator();
while (iterator.hasNext()) {
MiningBlock block = iterator.next();
if (mc.world.getBlockState(block.pos).isAir()) {
iterator.remove();
continue;
}
if (!block.mining) {
block.mine();
} else {
if (mc.player.age - block.startTime >= retryTime.getValue()) {
block.startTime = mc.player.age;
block.mining = false;
}
}
}
}
@SubscribeEvent
public void onAttackBlock(AttackBlockEvent event) {
event.cancel();
if (!isMining(event.getPos())) {
miningBlocks.add(new MiningBlock(event));
}
}
@SubscribeEvent
public void onRenderWorld(Render3DEvent event) {
for (MiningBlock block : miningBlocks) {
block.render(event);
}
}
private boolean isMining(BlockPos pos) {
for (MiningBlock block : miningBlocks) {
if (block.pos.equals(pos)) return true;
}
return false;
}
private class MiningBlock {
BlockPos pos;
Direction dir;
boolean mining;
long startTime;
public MiningBlock(AttackBlockEvent event) {
this.pos = event.getPos();
this.dir = event.getDir();
mining = false;
startTime = mc.player.age;
}
public void mine() {
if (pos.getSquaredDistance(mc.player.getEntityPos()) > Math.pow(mc.player.getBlockInteractionRange(), 2)
&& cancelOutOfReach.getValue()) {
return;
}
mc.interactionManager.sendSequencedPacket(mc.world, sequence ->
new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, pos, dir, sequence));
mining = true;
mc.interactionManager.sendSequencedPacket(mc.world, sequence ->
new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.STOP_DESTROY_BLOCK, pos, dir, sequence));
}
public void render(Render3DEvent event) {
VoxelShape shape = mc.world.getBlockState(pos).getOutlineShape(mc.world, pos);
RenderUtil.drawVoxelShapeOutline(
event.getMatrices(),
shape,
pos,
color.getValue(),
lineWidth.getFloatValue(),
false
);
}
}
}
@@ -24,7 +24,7 @@ public class AttributeSwapper extends Module {
@Override
public void onTick() {
if (mc.player == null || !swap.isEnabled()) return;
if (mc.player == null || !swap.getValue()) return;
if (delay < swapDelay.getIntValue()) delay++;
if (delay >= swapDelay.getIntValue() && prevSlot != -1) {
mc.player.getInventory().setSelectedSlot(prevSlot);
@@ -6,27 +6,68 @@ import me.retucio.sputnik.module.setting.settings.BooleanSetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import org.lwjgl.glfw.GLFW;
public class FastUse extends Module {
public BooleanSetting items = sgGeneral.add(new BooleanSetting("items", "usar items precozmente", true));
public NumberSetting itemCooldown = sgGeneral.add(new NumberSetting("cooldown de items", "cooldown para usar items en ticks", 0, 0, 4, 1));
public BooleanSetting items = sgGeneral.add(new BooleanSetting(
"items",
"usar items precozmente",
true
));
public NumberSetting itemCooldown = sgGeneral.add(new NumberSetting(
"cooldown de items",
"cooldown para usar items en ticks",
0,
0,
4,
1
));
public BooleanSetting blocks = sgGeneral.add(new BooleanSetting(
"bloques",
"colocar bloques precozmente",
true
));
public NumberSetting blockCooldown = sgGeneral.add(new NumberSetting(
"cooldown de bloques",
"cooldown para colocar bloques en ticks",
0,
0,
4,
1
));
public BooleanSetting mining = sgGeneral.add(new BooleanSetting(
"minar",
"minar precozmente",
true
));
public NumberSetting miningCooldown = sgGeneral.add(new NumberSetting(
"cooldown al minar",
"cooldown entre rotura de bloques en ticks",
5, 0, 20, 1
));
public BooleanSetting blocks = sgGeneral.add(new BooleanSetting("bloques", "colocar bloques precozmente", true));
public NumberSetting blockCooldown = sgGeneral.add(new NumberSetting("cooldown de bloques", "cooldown para colocar bloques en ticks", 0, 0, 4, 1));
public FastUse() {
super("precoz",
"hace cosas como usar items o colocar bloques más rápido",
Category.PLAYER);
Category.PLAYER,
GLFW.GLFW_KEY_F6);
items.onUpdate(v -> itemCooldown.setVisible(v));
blocks.onUpdate(v -> blockCooldown.setVisible(v));
}
public int getCooldown(ItemStack stack) {
if (stack.getItem() instanceof BlockItem && blocks.isEnabled()) return blockCooldown.getIntValue();
if (items.isEnabled() && !(stack.getItem() instanceof BlockItem)) return itemCooldown.getIntValue();
if (stack.getItem() instanceof BlockItem && blocks.getValue()) return blockCooldown.getIntValue();
if (items.getValue() && !(stack.getItem() instanceof BlockItem)) return itemCooldown.getIntValue();
else return 4; // cooldown por defecto, 4 ticks
}
}
@@ -50,15 +50,15 @@ public class InventoryPlus extends Module {
int rowOffset = InventoryUtil.getRowOffset(screen);
if (KeyUtil.isKeyDown(row1key.getKey())) {
if (KeyUtil.isKeyDown(row1key.getValue())) {
event.cancel();
swapWithRow(screen, containerSlot, hotbarKeyIndex, rowOffset);
}
else if (KeyUtil.isKeyDown(row2key.getKey())) {
else if (KeyUtil.isKeyDown(row2key.getValue())) {
event.cancel();
swapWithRow(screen, containerSlot, hotbarKeyIndex, rowOffset + 9);
}
else if (KeyUtil.isKeyDown(row3key.getKey())) {
else if (KeyUtil.isKeyDown(row3key.getValue())) {
event.cancel();
swapWithRow(screen, containerSlot, hotbarKeyIndex, rowOffset + 18);
}
@@ -0,0 +1,177 @@
package me.retucio.sputnik.module.modules.player;
import me.retucio.sputnik.event.SubscribeEvent;
import me.retucio.sputnik.event.events.PacketEvent;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.BooleanSetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting;
import me.retucio.sputnik.util.ChatUtil;
import net.minecraft.block.Blocks;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.Items;
import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket;
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
// https://github.com/etianl/Trouser-Streak/blob/ce27abd30435ca2b43a5e5546f5b070c07c6291a/src/main/java/pwn/noobs/trouserstreak/modules/MaceKill.java
public class MaceKill extends Module {
public BooleanSetting max = sgGeneral.add(new BooleanSetting(
"máxima potencia",
"simular caída desde el hueco con aire más cercano en un rango de 170 bloques",
false
));
public NumberSetting height = sgGeneral.add(new NumberSetting(
"altura",
"altura de la que simular la caída",
22,
1,
170,
1
));
public BooleanSetting preventDeath = sgGeneral.add(new BooleanSetting(
"prevenir muerte",
"prevenir la muerte por daño de caída si el ataque fue bloqueado, cancelando los paquetes de movimiento",
true
));
public MaceKill() {
super("estampaescrotos", "estampa escrotos ajenos", Category.PLAYER);
max.onUpdate(v -> height.setVisible(!v));
}
@SubscribeEvent
@SuppressWarnings("ConstantConditions")
public void onPacketSend(PacketEvent.Send event) {
if (mc.player == null) return;
if (mc.player.getMainHandStack().getItem() == Items.MACE
&& event.getPacket() instanceof PlayerInteractEntityC2SPacket packet
&& packet.type.getType() == PlayerInteractEntityC2SPacket.InteractType.ATTACK) {
try {
if (mc.world.getEntityById(packet.entityId) instanceof LivingEntity target) {
if (preventDeath.getValue()
&& (target.isBlocking()
|| target.isInvulnerable()
|| target.isInCreativeMode()
)) {
return;
}
Vec3d previouspos = mc.player.getEntityPos();
int blocks = getMaxHeightAbovePlayer();
int packetsRequired = (int) (double) Math.abs(blocks / 10);
if (packetsRequired > 20) {
packetsRequired = 1;
}
BlockPos gap1 = (mc.player.getBlockPos().add(0, blocks, 0));
BlockPos gap2 = (mc.player.getBlockPos().add(0, blocks + 1, 0));
if (isSafeBlock(gap1) && isSafeBlock(gap2)) {
if (blocks <= 22) {
if (mc.player.hasVehicle()) {
for (int i = 0; i < 4; i++) {
mc.player.networkHandler.sendPacket(VehicleMoveC2SPacket.fromVehicle(mc.player.getVehicle()));
}
double maxHeight = Math.min(mc.player.getVehicle().getY() + 22, mc.player.getVehicle().getY() + blocks);
mc.player.getVehicle().setPosition(mc.player.getVehicle().getX(), maxHeight + blocks, mc.player.getVehicle().getZ());
mc.player.networkHandler.sendPacket(VehicleMoveC2SPacket.fromVehicle(mc.player.getVehicle()));
mc.player.getVehicle().setPosition(previouspos);
mc.player.networkHandler.sendPacket(VehicleMoveC2SPacket.fromVehicle(mc.player.getVehicle()));
} else {
for (int i = 0; i < 4; i++) {
mc.player.networkHandler.sendPacket(new PlayerMoveC2SPacket.OnGroundOnly(false, mc.player.horizontalCollision));
}
double maxHeight = Math.min(mc.player.getY() + 22, mc.player.getY() + blocks);
PlayerMoveC2SPacket movePacket = new PlayerMoveC2SPacket.PositionAndOnGround(mc.player.getX(), maxHeight, mc.player.getZ(), false, mc.player.horizontalCollision);
mc.player.networkHandler.sendPacket(movePacket);
PlayerMoveC2SPacket returnPacket = new PlayerMoveC2SPacket.PositionAndOnGround(previouspos.getX(), previouspos.getY(), previouspos.getZ(), false, mc.player.horizontalCollision);
mc.player.networkHandler.sendPacket(returnPacket);
}
} else {
if (mc.player.hasVehicle()) {
for (int packetNumber = 0; packetNumber < (packetsRequired - 1); packetNumber++) {
mc.player.networkHandler.sendPacket(VehicleMoveC2SPacket.fromVehicle(mc.player.getVehicle()));
}
mc.player.getVehicle().setPosition(mc.player.getVehicle().getX(), mc.player.getVehicle().getY() + blocks, mc.player.getVehicle().getZ());
double maxHeight = mc.player.getVehicle().getY() + blocks;
mc.player.getVehicle().setPosition(mc.player.getVehicle().getX(), maxHeight + blocks, mc.player.getVehicle().getZ());
mc.player.networkHandler.sendPacket(VehicleMoveC2SPacket.fromVehicle(mc.player.getVehicle()));
mc.player.getVehicle().setPosition(previouspos);
mc.player.networkHandler.sendPacket(VehicleMoveC2SPacket.fromVehicle(mc.player.getVehicle()));
} else {
for (int packetNumber = 0; packetNumber < (packetsRequired - 1); packetNumber++) {
mc.player.networkHandler.sendPacket(new PlayerMoveC2SPacket.OnGroundOnly(false, mc.player.horizontalCollision));
}
mc.player.networkHandler.sendPacket(new PlayerMoveC2SPacket.PositionAndOnGround(mc.player.getX(), mc.player.getY() + blocks, mc.player.getZ(), false, mc.player.horizontalCollision));
PlayerMoveC2SPacket movePacket = new PlayerMoveC2SPacket.PositionAndOnGround(mc.player.getX(), mc.player.getY() + blocks, mc.player.getZ(), false, mc.player.horizontalCollision);
mc.player.networkHandler.sendPacket(movePacket);
}
if (mc.player.hasVehicle()) {
mc.player.getVehicle().setPosition(previouspos);
mc.player.networkHandler.sendPacket(VehicleMoveC2SPacket.fromVehicle(mc.player.getVehicle()));
mc.player.getVehicle().setPosition(previouspos);
mc.player.networkHandler.sendPacket(VehicleMoveC2SPacket.fromVehicle(mc.player.getVehicle()));
} else {
double maxHeight = mc.player.getY() + blocks;
PlayerMoveC2SPacket movePacket = new PlayerMoveC2SPacket.PositionAndOnGround(mc.player.getX(), maxHeight, mc.player.getZ(), false, mc.player.horizontalCollision);
PlayerMoveC2SPacket returnPacket = new PlayerMoveC2SPacket.PositionAndOnGround(previouspos.getX(), previouspos.getY(), previouspos.getZ(), false, mc.player.horizontalCollision);
mc.player.networkHandler.sendPacket(returnPacket);
mc.player.networkHandler.sendPacket(movePacket);
mc.player.networkHandler.sendPacket(returnPacket);
}
}
}
}
} catch (Exception e) {
ChatUtil.error("upsi: " + e.getMessage());
}
}
}
private int getMaxHeightAbovePlayer() {
BlockPos playerPos = mc.player.getBlockPos();
int maxHeight = playerPos.getY() + (max.getValue() ? 170 : height.getIntValue());
for (int i = maxHeight; i > playerPos.getY(); i--) {
BlockPos isopenair1 = new BlockPos(playerPos.getX(), i, playerPos.getZ());
BlockPos isopenair2 = isopenair1.up(1);
if (isSafeBlock(isopenair1) && isSafeBlock(isopenair2)) {
return i - playerPos.getY();
}
}
return 0;
}
private boolean isSafeBlock(BlockPos pos) {
return mc.world.getBlockState(pos).isReplaceable()
&& mc.world.getFluidState(pos).isEmpty()
&& !mc.world.getBlockState(pos).isOf(Blocks.POWDER_SNOW);
}
}
@@ -46,7 +46,7 @@ public class Offhand extends Module {
}
if (holdingItem || (!mc.player.getOffHandStack().isEmpty()
&& !override.isEnabled()))
&& !override.getValue()))
return;
if (mc.player.playerScreenHandler == mc.player.currentScreenHandler) {
@@ -60,7 +60,7 @@ public class WarnLowDurability extends Module {
float percentage = (1 - (float) stack.getDamage() / stack.getMaxDamage()) * 100;
if (percentage <= limitPercentage.getValue() && percentage < prevPercentage) {
if (playSound.isEnabled())
if (playSound.getValue())
mc.world.playSound(mc.player, mc.player.getBlockPos(),
sound.getValue(),
SoundCategory.AMBIENT,
@@ -68,7 +68,7 @@ public class WarnLowDurability extends Module {
toExponential(pitch)
);
if (message.isEnabled()) {
if (message.getValue()) {
String customName = stack.getCustomName() == null ? "" : " \"" + stack.getCustomName().getString() + "\"";
Text text = Text.literal(Formatting.AQUA + stack.getItemName().getString()
+ Formatting.GREEN + customName + Formatting.RESET
@@ -14,30 +14,96 @@ import me.retucio.sputnik.util.Lists;
import me.retucio.sputnik.util.render.RenderUtil;
import net.minecraft.block.Block;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3i;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.shape.VoxelShape;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class BlockESP extends Module {
SettingGroup sgSearch = addSg(new SettingGroup("búsqueda", true));
SettingGroup sgOulines = addSg(new SettingGroup("contorno", true));
SettingGroup sgFilling = addSg(new SettingGroup("relleno", true));
public ListSetting<Block> blocks = sgGeneral.add(new ListSetting<>("bloques", "bloques a resaltar",
Lists.blockList, Lists.allFalse(Lists.blockList), Lists.blockNames));
public NumberSetting radius = sgGeneral.add(new NumberSetting("radio", "radio de búsqueda de bloques",
24, 2, 128, 1));
public BooleanSetting outlines = sgOulines.add(new BooleanSetting("contorno", "renderizar contorno de bloques", true));
public ColorSetting outlineColor = sgOulines.add(new ColorSetting("color del contorno", "color del contorno", Colors.CELESTE, false));
public NumberSetting lineWidth = sgOulines.add(new NumberSetting("grosor del contorno", "grosor de las líneas del contorno", 1, 1, 5, 0.2));
// bloques
public BooleanSetting fillings = sgFilling.add(new BooleanSetting("relleno", "renderizar relleno de bloques", true));
public ColorSetting fillingColor = sgFilling.add(new ColorSetting("color del relleno", "color del relleno", new Color(57, 177, 215, 67), false));
public ListSetting<Block> blocks = sgGeneral.add(new ListSetting<>(
"bloques", "bloques a resaltar",
Lists.blockList,
Lists.allFalse(Lists.blockList),
Lists.blockNames
));
public NumberSetting maxBlocks = sgGeneral.add(new NumberSetting(
"máx. bloques", "número máximo de bloques a resaltar",
500, 1, 2000, 1
));
// búsqueda
public NumberSetting radius = sgSearch.add(new NumberSetting(
"radio", "radio de búsqueda de bloques",
24, 2, 128, 1
));
public NumberSetting searchInterval = sgSearch.add(new NumberSetting(
"intervalo", "intervalo de búsqueda en ticks",
10, 1, 40, 1
));
public BooleanSetting asyncSearch = sgSearch.add(new BooleanSetting(
"búsqueda asíncrona", "busca los bloques en un hilo separado (optimización)",
true
));
public NumberSetting distanceToMove = sgSearch.add(new NumberSetting(
"distancia a moverse", "distancia a moverse antes de actualizar los bloques",
3, 0, 10, 0.1
));
// contorno
public BooleanSetting outlines = sgOulines.add(new BooleanSetting(
"contorno", "renderizar contorno de bloques",
true
));
public ColorSetting outlineColor = sgOulines.add(new ColorSetting(
"color del contorno", "color del contorno",
Colors.CELESTE, false
));
public NumberSetting lineWidth = sgOulines.add(new NumberSetting(
"grosor del contorno", "grosor de las líneas del contorno",
1, 1, 5, 0.2
));
// relleno
public BooleanSetting fillings = sgFilling.add(new BooleanSetting(
"relleno", "renderizar relleno de bloques",
true
));
public ColorSetting fillingColor = sgFilling.add(new ColorSetting(
"color del relleno", "color del relleno",
new Color(57, 177, 215, 67), false
));
// caché
private final Map<BlockPos, VoxelShape> cachedBlocks = new ConcurrentHashMap<>();
private final Set<Block> enabledBlocks = Collections.newSetFromMap(new ConcurrentHashMap<>());
private BlockPos lastPlayerPos = null;
private int lastRadius = -1;
private int searchTimer = 0;
private boolean isSearching = false;
public BlockESP() {
@@ -45,61 +111,166 @@ public class BlockESP extends Module {
"te muestra la posición de cierto tipo de bloque renderizando una caja con su forma",
Category.RENDER);
blocks.onUpdate(v ->
updateEnabledBlocks()
);
outlines.onUpdate(v -> {
outlineColor.setVisible(v);
lineWidth.setVisible(v);
});
fillings.onUpdate(v -> fillingColor.setVisible(v));
fillings.onUpdate(v ->
fillingColor.setVisible(v)
);
}
@Override
public void onEnable() {
cachedBlocks.clear();
enabledBlocks.clear();
updateEnabledBlocks();
searchTimer = 0;
super.onEnable();
}
@Override
public void onDisable() {
cachedBlocks.clear();
enabledBlocks.clear();
super.onDisable();
}
@SubscribeEvent
public void onRenderWorld(Render3DEvent event) {
if (mc.player == null || mc.world == null) return;
for (Block block : blocks.getOptions()) {
if (blocks.isEnabled(block)) {
List<BlockPos> blocksToHighlight = getNearbyBlocks(block);
for (BlockPos pos : blocksToHighlight) {
if (outlines.isEnabled()) {
RenderUtil.drawVoxelShapeOutline(
event.getMatrices(),
getVoxelShape(pos),
pos,
outlineColor.getColor(),
lineWidth.getFloatValue(),
false);
}
if (fillings.isEnabled()) {
RenderUtil.drawVoxelShapeFilled(
event.getMatrices(),
getVoxelShape(pos),
pos,
fillingColor.getColor(),
false);
// aplicar el intervalo
if (searchTimer++ >= searchInterval.getIntValue()) {
searchTimer = 0;
searchBlocks();
}
Vec3d cameraPos = mc.gameRenderer.getCamera().getCameraPos();
int rendered = 0;
Iterator<Map.Entry<BlockPos, VoxelShape>> iterator = cachedBlocks.entrySet().iterator();
while (iterator.hasNext() && rendered < maxBlocks.getIntValue()) {
Map.Entry<BlockPos, VoxelShape> entry = iterator.next();
BlockPos pos = entry.getKey();
VoxelShape shape = entry.getValue();
if (!isValidBlock(pos)) {
iterator.remove();
continue;
}
// validación de distancia
double distance = Math.sqrt(pos.getSquaredDistance(cameraPos));
if (distance > radius.getIntValue()) {
iterator.remove();
continue;
}
// renderizado
if (outlines.getValue()) {
Color color = outlineColor.getValue();
RenderUtil.drawVoxelShapeOutline(
event.getMatrices(),
shape,
pos,
color,
lineWidth.getFloatValue(),
false);
}
if (fillings.getValue()) {
Color color = fillingColor.getValue();
RenderUtil.drawVoxelShapeFilled(
event.getMatrices(),
shape,
pos,
color,
false);
}
rendered++;
}
}
private void updateEnabledBlocks() {
enabledBlocks.clear();
enabledBlocks.addAll(blocks.getEnabledOptions());
}
private void searchBlocks() {
if (mc.player == null || mc.world == null || enabledBlocks.isEmpty()) return;
BlockPos playerPos = mc.player.getBlockPos();
int currentRadius = radius.getIntValue();
// si el jugador no se ha movido mucho, omitir la búsqueda
if (lastPlayerPos != null && lastRadius == currentRadius &&
playerPos.getSquaredDistance(lastPlayerPos) < (distanceToMove.getValue() * distanceToMove.getIntValue())) {
return;
}
lastPlayerPos = playerPos;
lastRadius = currentRadius;
// multithreading
if (asyncSearch.getValue()) {
if (isSearching) return;
isSearching = true;
new Thread(() -> {
try {
performBlockSearch(playerPos, currentRadius);
} finally {
isSearching = false;
}
}, "sputnik-blockESP-search").start();
} else {
performBlockSearch(playerPos, currentRadius);
}
}
// buscar los bloques
private void performBlockSearch(BlockPos center, int radius) {
Map<BlockPos, VoxelShape> newBlocks = new HashMap<>();
int radiusSq = radius * radius;
for (int x = -radius; x <= radius; x++) {
for (int y = -radius; y <= radius; y++) {
for (int z = -radius; z <= radius; z++) {
if (x*x + y*y + z*z > radiusSq) continue;
BlockPos pos = center.add(x, y, z);
Block block = mc.world.getBlockState(pos).getBlock();
if (enabledBlocks.contains(block)) {
VoxelShape shape = mc.world.getBlockState(pos).getOutlineShape(mc.world, pos);
if (!shape.isEmpty()) {
newBlocks.put(pos.toImmutable(), shape);
}
}
}
}
}
// actualizar caché
cachedBlocks.keySet().retainAll(newBlocks.keySet());
cachedBlocks.putAll(newBlocks);
}
private List<BlockPos> getNearbyBlocks(Block block) {
List<BlockPos> blockPosList = new ArrayList<>();
for (int i = -radius.getIntValue(); i < radius.getIntValue(); i++) {
for (int j = -radius.getIntValue(); j < radius.getIntValue(); j++) {
for (int k = -radius.getIntValue(); k < radius.getIntValue(); k++) {
BlockPos pos = mc.player.getBlockPos().add(new Vec3i(i, j, k));
if (mc.world.getBlockState(pos).getBlock() == block) {
blockPosList.add(pos);
}
}
}
}
return blockPosList;
}
private VoxelShape getVoxelShape(BlockPos pos) {
return mc.world.getBlockState(pos).getOutlineShape(mc.world, pos);
// verificar que el bloque sea válido
@SuppressWarnings("deprecation")
private boolean isValidBlock(BlockPos pos) {
if (mc.world == null || !mc.world.isChunkLoaded(pos)) return false;
Block block = mc.world.getBlockState(pos).getBlock();
return enabledBlocks.contains(block);
}
}
@@ -3,6 +3,8 @@ package me.retucio.sputnik.module.modules.render;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.ColorSetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting;
import me.retucio.sputnik.util.Colors;
import java.awt.*;
@@ -12,8 +14,21 @@ import java.awt.*;
public class BlockOutline extends Module {
public ColorSetting color = sgGeneral.add(new ColorSetting("color", "color del contorno de los bloques",
new Color(0, 0, 0, 102), true));
public ColorSetting color = sgGeneral.add(new ColorSetting(
"color",
"color del contorno de los bloques",
Colors.mainColor,
true)
);
public NumberSetting lineWidth = sgGeneral.add(new NumberSetting(
"grosor",
"grosor de las líneas",
0.5,
0.1,
10,
0.1
));
public BlockOutline() {
super("contorno",
@@ -73,8 +73,8 @@ public class BreakingProgress extends Module {
centerX + shrunkX, centerY + shrunkZ, centerZ + shrunkZ
);
if (outlines.isEnabled()) RenderUtil.drawOutlineBox(event.getMatrices(), scaledBox, outlineColor.getColor(), lineWidth.getFloatValue(), false);
if (fillings.isEnabled()) RenderUtil.drawFilledBox(event.getMatrices(), scaledBox, fillingColor.getColor(), false);
if (outlines.getValue()) RenderUtil.drawOutlineBox(event.getMatrices(), scaledBox, outlineColor.getValue(), lineWidth.getFloatValue(), false);
if (fillings.getValue()) RenderUtil.drawFilledBox(event.getMatrices(), scaledBox, fillingColor.getValue(), false);
}
public enum BreakMode {
@@ -6,6 +6,7 @@ import me.retucio.sputnik.module.setting.SettingGroup;
import me.retucio.sputnik.module.setting.settings.BooleanSetting;
import me.retucio.sputnik.module.setting.settings.ColorSetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting;
import me.retucio.sputnik.util.Colors;
import java.awt.*;
@@ -19,7 +20,7 @@ public class CritsPlus extends Module {
SettingGroup sgAppearance = addSg(new SettingGroup("aspecto", true));
SettingGroup sgBehaviour = addSg(new SettingGroup("funcionamiento", true));
public ColorSetting color = sgAppearance.add(new ColorSetting("color", "color de las partículas", new Color(0, 0, 255, 255), false));
public ColorSetting color = sgAppearance.add(new ColorSetting("color", "color de las partículas", Colors.mainColor, false));
public NumberSetting scale = sgAppearance.add(new NumberSetting("escala", "tamaño", 1, 0, 2, 0.05));
public NumberSetting multiplier = sgAppearance.add(new NumberSetting("múltiplo", "número por el que multiplicar la cantidad de partículas generadas", 1, 0, 10, 0.1));
@@ -5,6 +5,7 @@ import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.ColorSetting;
import me.retucio.sputnik.util.Colors;
import net.minecraft.client.texture.NativeImage;
import net.minecraft.client.texture.NativeImageBackedTexture;
@@ -16,7 +17,12 @@ import java.awt.*;
public class DamageOverlay extends Module {
public ColorSetting colorSetting = sgGeneral.add(new ColorSetting("color", "color", new Color(255, 0, 0, 77), false));
public ColorSetting colorSetting = sgGeneral.add(new ColorSetting(
"color",
"color",
Colors.mainColor,
false
));
private NativeImageBackedTexture texture = null;
@@ -0,0 +1,45 @@
package me.retucio.sputnik.module.modules.render;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.settings.BooleanSetting;
import me.retucio.sputnik.module.setting.settings.OptionSetting;
import me.retucio.sputnik.util.Lists;
public class Fonts extends Module {
public OptionSetting<String> font = sgGeneral.add(new OptionSetting<>(
"fuente", "fuente a emplear",
Lists.fontList, "ubuntu")
);
public BooleanSetting reload = sgGeneral.add(new BooleanSetting(
"recargar", "recargar automáticamente",
false
));
public Fonts() {
super("fuentes",
"modifica el tipo de letra utilizado al renderizar texto",
Category.RENDER);
font.onUpdate(v -> reload());
}
@Override
public void onEnable() {
reload();
}
@Override
public void onDisable() {
reload();
}
private void reload() {
if (mc.getResourceManager() != null && reload.getValue()) {
mc.reloadResources();
}
}
}
@@ -17,9 +17,24 @@ import net.minecraft.util.DyeColor;
public class GlintPlus extends Module {
public BooleanSetting items = sgGeneral.add(new BooleanSetting("items", "modificar el destello de encantamiento de los items", true));
public BooleanSetting armor = sgGeneral.add(new BooleanSetting("armadura", "modificar el destello de encantamiento de la armadura", true));
public EnumSetting<GlintColors> glintColor = sgGeneral.add(new EnumSetting<>("colores", "color del glint", GlintColors.class, GlintColors.PURPLE));
public BooleanSetting items = sgGeneral.add(new BooleanSetting(
"items",
"modificar el destello de encantamiento de los items",
true
));
public BooleanSetting armor = sgGeneral.add(new BooleanSetting(
"armadura",
"modificar el destello de encantamiento de la armadura",
true
));
public EnumSetting<GlintColors> glintColor = sgGeneral.add(new EnumSetting<>(
"colores",
"color del glint",
GlintColors.class,
GlintColors.PURPLE
));
public GlintPlus() {
super("destello de enchants.",
@@ -29,19 +44,19 @@ public class GlintPlus extends Module {
public RenderLayer getGlint() {
int color = getColor();
if (!isEnabled() || !items.isEnabled()) return RenderLayers.glint();
if (!isEnabled() || !items.getValue()) return RenderLayers.glint();
return GlintRenderLayer.glintColor.get(color);
}
public RenderLayer getEntityGlint() {
int color = getColor();
if (!isEnabled() || !items.isEnabled()) return RenderLayers.entityGlint();
if (!isEnabled() || !items.getValue()) return RenderLayers.entityGlint();
return GlintRenderLayer.entityGlintColor.get(color);
}
public RenderLayer getArmorEntityGlint() {
int color = getColor();
if (!isEnabled() || !armor.isEnabled()) return RenderLayers.armorEntityGlint();
if (!isEnabled() || !armor.getValue()) return RenderLayers.armorEntityGlint();
return GlintRenderLayer.armorEntityGlintColor.get(color);
}
@@ -73,7 +73,7 @@ public class Nametags extends Module {
defaultEntities.replace(EntityType.ARROW, true);
defaultEntities.replace(EntityType.SPECTRAL_ARROW, true);
defaultEntities.replace(EntityType.TRIDENT, true);
entities.setDefaultValues(defaultEntities);
entities.setDefaultValue(defaultEntities);
health.onUpdate(v -> healthMode.setVisible(v));
@@ -0,0 +1,189 @@
package me.retucio.sputnik.module.modules.render;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.SettingGroup;
import me.retucio.sputnik.module.setting.settings.ListSetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting;
import me.retucio.sputnik.util.Lists;
import net.minecraft.particle.SimpleParticleType;
import net.minecraft.registry.Registries;
import net.minecraft.text.Text;
import net.minecraft.util.math.Vec3d;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class Particles extends Module {
SettingGroup sgDispersion = addSg(new SettingGroup("dispersión", true));
SettingGroup sgOffset = addSg(new SettingGroup("desplazamiento", true));
List<SimpleParticleType> particleList = Lists.particleList.stream()
.filter(particleType -> particleType instanceof SimpleParticleType)
.map(particleType -> (SimpleParticleType) particleType)
.toList();
Map<SimpleParticleType, String> particleNames = Lists.getMapOfLists(particleList,
particleList.stream().map(particle -> Text.translatable(
Registries.PARTICLE_TYPE.getId(particle).toShortTranslationKey()).getString()
).toList());
public ListSetting<SimpleParticleType> particles = sgGeneral.add(new ListSetting<>(
"partículas",
"partículas a generar",
particleList,
Lists.allFalse(particleList),
particleNames
));
public NumberSetting spawnInterval = sgGeneral.add(new NumberSetting(
"intervalo",
"intervalo entre generaciones (en ticks)",
4, 1, 100, 1
));
public NumberSetting particleCount = sgGeneral.add(new NumberSetting(
"cantidad",
"partículas por generación",
10, 1, 100, 1
));
public NumberSetting velocity = sgDispersion.add(new NumberSetting(
"velocidad",
"multiplicador de la velocidad de dispersión",
0.2, 0, 2, 0.05
));
public NumberSetting spreadX = sgDispersion.add(new NumberSetting(
"dispersión X",
"dispersión horizontal de posición",
0.5, 0, 5, 0.1
));
public NumberSetting spreadY = sgDispersion.add(new NumberSetting(
"dispersión Y",
"dispersión vertical de posición",
0.5, 0, 5, 0.1
));
public NumberSetting spreadZ = sgDispersion.add(new NumberSetting(
"dispersión Z",
"dispersión de profundidad de posición",
0.5, 0, 5, 0.1
));
public NumberSetting velocityRandomness = sgDispersion.add(new NumberSetting(
"aleatoriedad velocidad",
"variación aleatoria en la velocidad",
0.3, 0, 1, 0.05
));
public NumberSetting positionRandomness = sgDispersion.add(new NumberSetting(
"aleatoriedad posición",
"variación aleatoria en la posición",
0.2, 0, 1, 0.05
));
public NumberSetting offsetX = sgOffset.add(new NumberSetting(
"desplazamiento pos. X",
"desplazamiento en el eje X respecto al jugador",
0, -1, 1, 0.01
));
public NumberSetting offsetY = sgOffset.add(new NumberSetting(
"desplazamiento pos. Y",
"desplazamiento en el eje Y respecto al jugador",
0, -1, 1, 0.01
));
public NumberSetting offsetZ = sgOffset.add(new NumberSetting(
"desplazamiento pos. Z",
"desplazamiento en el eje Z respecto al jugador",
-0.8, -1, 1, 0.01
));
private final Random random = new Random();
private int tickCounter = 0;
public Particles() {
super("partículas", "emite particulas artificiales", Category.RENDER);
}
@Override
public void onEnable() {
tickCounter = 0;
super.onEnable();
}
@Override
public void onTick() {
if (mc.player == null || mc.world == null) return;
tickCounter++;
if (tickCounter < spawnInterval.getIntValue()) {
return;
}
tickCounter = 0;
List<SimpleParticleType> enabledParticles = particles.getEnabledOptions();
if (enabledParticles.isEmpty()) return;
Vec3d basePos = new Vec3d(
mc.player.getX(),
mc.player.getY() + mc.player.getEyeHeight(mc.player.getPose()),
mc.player.getZ()
);
for (int i = 0; i < particleCount.getIntValue(); i++) {
SimpleParticleType particle = enabledParticles.get(
random.nextInt(enabledParticles.size())
);
Vec3d pos = getPos(basePos);
Vec3d vel = getVel();
double yaw = Math.toRadians(mc.player.getYaw());
double offX = offsetX.getValue() * Math.cos(yaw) - offsetZ.getValue() * Math.sin(yaw);
double offZ = offsetX.getValue() * Math.sin(yaw) + offsetZ.getValue() * Math.cos(yaw);
mc.world.addParticleClient(
particle,
pos.x + offX,
pos.y + offsetY.getValue(),
pos.z + offZ,
vel.x, vel.y, vel.z
);
}
}
private Vec3d getPos(Vec3d basePos) {
double randX = (random.nextDouble() - 0.5) * 2 * positionRandomness.getValue();
double randY = (random.nextDouble() - 0.5) * 2 * positionRandomness.getValue();
double randZ = (random.nextDouble() - 0.5) * 2 * positionRandomness.getValue();
return new Vec3d(
basePos.x + (random.nextDouble() - 0.5) * spreadX.getValue() + randX,
basePos.y + (random.nextDouble() - 0.5) * spreadY.getValue() + randY,
basePos.z + (random.nextDouble() - 0.5) * spreadZ.getValue() + randZ
);
}
private Vec3d getVel() {
double randX = (random.nextDouble() - 0.5) * 2 * velocityRandomness.getValue();
double randY = (random.nextDouble() - 0.5) * 2 * velocityRandomness.getValue();
double randZ = (random.nextDouble() - 0.5) * 2 * velocityRandomness.getValue();
return new Vec3d(
(random.nextDouble() - 0.5) * velocity.getValue() + randX,
(random.nextDouble() - 0.5) * velocity.getValue() + randY,
(random.nextDouble() - 0.5) * velocity.getValue() + randZ
);
}
}
@@ -0,0 +1,95 @@
package me.retucio.sputnik.module.modules.world;
import com.google.gson.Gson;
import me.retucio.sputnik.event.SubscribeEvent;
import me.retucio.sputnik.event.events.KeyEvent;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.module.setting.SettingGroup;
import me.retucio.sputnik.module.setting.settings.BooleanSetting;
import me.retucio.sputnik.module.setting.settings.EnumSetting;
import me.retucio.sputnik.module.setting.settings.KeySetting;
import me.retucio.sputnik.util.ChatUtil;
import me.retucio.sputnik.util.KeyUtil;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Property;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.Vec3d;
import org.lwjgl.glfw.GLFW;
import java.util.Collection;
// copy summon / setblock command
// copy json data to clipboard
// print data (keybinds)
public class BlockInfo extends Module {
public KeySetting key = sgGeneral.add(new KeySetting(
"tecla",
"tecla a pulsar para obtener la info.",
GLFW.GLFW_KEY_CAPS_LOCK
));
public EnumSetting<CopyMode> copy = sgGeneral.add(new EnumSetting<>(
"copiar",
"copiar al portapapeles",
CopyMode.class,
CopyMode.COMMAND
));
public BlockInfo() {
super("info. de bloque",
"muestra el contenido nbt del bloque al que se está apuntando",
Category.WORLD);
}
@SubscribeEvent
public void onKey(KeyEvent event) {
if (mc.player == null || mc.world == null) return;
if (event.getKey() != key.getValue() || event.getAction() != GLFW.GLFW_PRESS) return;
HitResult result = mc.player.getCrosshairTarget(
mc.getRenderTickCounter().getTickProgress(false),
mc.getCameraEntity()
);
if (result == null) {
ChatUtil.warn("no estás apuntando a ningún bloque");
return;
}
if (result instanceof BlockHitResult blockHitResult) {
BlockState state = mc.world.getBlockState(blockHitResult.getBlockPos());
Collection<Property<?>> data = state.getProperties();
for (Property<?> property : data) {
ChatUtil.info(property.getName() + ": " + state.get(property));
}
copy(blockHitResult, data);
} else {
ChatUtil.warn("no estás apuntando a ningún bloque");
}
}
private void copy(BlockHitResult result, Collection<Property<?>> data) {
String json = new Gson().toJson(data);
String name = mc.world.getBlockState(result.getBlockPos()).getBlock().getTranslationKey();
Vec3d pos = result.getPos();
switch (copy.getValue()) {
case JSON -> mc.keyboard.setClipboard(json);
case COMMAND -> mc.keyboard.setClipboard(
String.format("/setblock %f %f %f %s %s", pos.x, pos.y, pos.z, name, json));
}
}
public enum CopyMode {
DONT("no copiar"),
COMMAND("copiar comando /setblock"),
JSON("copiar contenido json");
private final String name;
CopyMode(String name) { this.name = name; }
@Override public String toString() { return name; }
}
}
@@ -10,140 +10,350 @@ import me.retucio.sputnik.module.setting.settings.ColorSetting;
import me.retucio.sputnik.module.setting.settings.NumberSetting;
import me.retucio.sputnik.util.render.RenderUtil;
import net.minecraft.block.*;
import net.minecraft.block.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.Heightmap;
import net.minecraft.world.LightType;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class LightOverlay extends Module {
SettingGroup sgDetection = addSg(new SettingGroup("detección", true));
SettingGroup sgColors = addSg(new SettingGroup("colores", true));
SettingGroup sgOptimization = addSg(new SettingGroup("optimización", true));
public NumberSetting radius = sgDetection.add(new NumberSetting("radio", "radio a tener en cuenta al renderizar superposición",
// detección
public NumberSetting radius = sgDetection.add(new NumberSetting(
"radio",
"radio a tener en cuenta al renderizar superposición",
16, 5, 128, 1));
public NumberSetting yRadius = sgDetection.add(new NumberSetting("rango vertical", "distancia vertical a tener en cuenta",
public NumberSetting yRadius = sgDetection.add(new NumberSetting(
"rango vertical",
"distancia vertical a tener en cuenta",
4, 1, 16, 1));
public NumberSetting interval = sgDetection.add(new NumberSetting("intervalo", "cada cuántos ticks comprobar el nivel de luz",
public BooleanSetting onWater = sgDetection.add(new BooleanSetting(
"en agua",
"mostrar también bloques cubiertos en agua", true));
public BooleanSetting dontCullWater = sgDetection.add(new BooleanSetting(
"evitar culling en agua",
"mostrar superposición a través de bloques para poder verla desde fuera del agua", false));
// optimización, porque iba como la mierda
public NumberSetting updateInterval = sgOptimization.add(new NumberSetting(
"intervalo de búsqueda",
"cada cuántos ticks actualizar la búsqueda de bloques",
10, 1, 80, 1));
public BooleanSetting onWater = sgDetection.add(new BooleanSetting("en agua", "mostrar también bloques cubiertos en agua", true));
public BooleanSetting dontCullWater = sgDetection.add(new BooleanSetting("evitar culling en agua", "mostrar superposición a través de bloques para poder verla desde fuera del agua", false));
public NumberSetting movementThreshold = sgOptimization.add(new NumberSetting(
"umbral de movimiento",
"distancia que debe moverse el jugador antes de forzar una actualización",
3.0, 0.5, 10.0, 0.5));
public ColorSetting lightColor = sgColors.add(new ColorSetting("color de la luz", "color de los bloques con luz",
public BooleanSetting asyncSearch = sgOptimization.add(new BooleanSetting(
"búsqueda asíncrona",
"buscar bloques en un hilo separado (reduce lag)",
true));
public BooleanSetting incrementalUpdates = sgOptimization.add(new BooleanSetting(
"actualizaciones incrementales",
"actualizar solo los bloques nuevos / eliminados en lugar de recalcular todo",
true));
// colores
public ColorSetting lightColor = sgColors.add(new ColorSetting(
"color de la luz",
"color de los bloques con luz",
new Color(0, 255, 0, 67), false));
public ColorSetting darknessColor = sgColors.add(new ColorSetting("color de oscuridad", "color de bloques con 0 luz",
public ColorSetting darknessColor = sgColors.add(new ColorSetting(
"color de oscuridad",
"color de bloques con 0 luz",
new Color(255, 0, 0, 67), false));
List<BlockPos> blocks = new ArrayList<>();
// caché y estado
private final Set<BlockPos> cachedBlocks = Collections.newSetFromMap(new ConcurrentHashMap<>());
private final Set<BlockPos> blocksToRender = Collections.newSetFromMap(new ConcurrentHashMap<>());
private BlockPos lastPlayerPos = null;
private int lastRadius = -1;
private int lastYRadius = -1;
private int updateTimer = 0;
private boolean isSearching = false;
// para actualizaciones incrementales
private int incrementalLayer = 0;
private boolean fullRescanNeeded = false;
public LightOverlay() {
super("superposición de luz",
"te muestra el nivel de luz en bloques, para prevenir mob spawns",
Category.WORLD);
onWater.onUpdate(v -> dontCullWater.setVisible(v));
}
@Override
public void onEnable() {
cachedBlocks.clear();
blocksToRender.clear();
lastPlayerPos = null;
lastRadius = -1;
lastYRadius = -1;
updateTimer = 0;
incrementalLayer = 0;
fullRescanNeeded = true;
super.onEnable();
}
@Override
public void onDisable() {
cachedBlocks.clear();
blocksToRender.clear();
super.onDisable();
}
@SubscribeEvent
@SuppressWarnings("deprecation")
public void onRenderWorld(Render3DEvent event) {
if (mc.player == null || mc.world == null) return;
if (mc.player.age % interval.getIntValue() == 0) {
blocks = findExposedBlocks(
radius.getIntValue(),
yRadius.getIntValue()
);
// actualización periódica
if (updateTimer++ >= updateInterval.getIntValue()) {
updateTimer = 0;
updateBlocks();
}
for (BlockPos block : blocks) {
if (mc.world.getBlockState(block).isAir() || !canSpawnOn(block)) continue;
if (!mc.world.getBlockState(block).isOpaque()) continue;
// renderizado
Vec3d cameraPos = mc.gameRenderer.getCamera().getCameraPos();
int radiusValue = radius.getIntValue();
double radiusSq = radiusValue * radiusValue;
// actualizar lista de renderizado basado en distancia
blocksToRender.clear();
for (BlockPos pos : cachedBlocks) {
double distanceSq = pos.getSquaredDistance(cameraPos);
if (distanceSq <= radiusSq) {
blocksToRender.add(pos);
}
}
// renderizar bloques visibles
for (BlockPos block : blocksToRender) {
if (!mc.world.isChunkLoaded(block)) continue;
BlockState state = mc.world.getBlockState(block);
BlockState aboveState = mc.world.getBlockState(block.up());
if (!isValidSpawnSurface(block, state, aboveState)) continue;
// nivel de luz
int light = mc.world.getLightLevel(LightType.BLOCK, block.up());
Color color = light == 0 ? darknessColor.getColor()
: new Color(
(lightColor.getR() / 15) * light,
(lightColor.getG() / 15) * light,
(lightColor.getB() / 15) * light,
lightColor.getA());
// color
Color color;
if (light == 0) {
color = darknessColor.getValue();
} else {
float ratio = light / 15.0f;
color = new Color(
(int)(lightColor.getR() * ratio),
(int)(lightColor.getG() * ratio),
(int)(lightColor.getB() * ratio),
lightColor.getA()
);
}
boolean shouldCull = !(onWater.isEnabled() && mc.world.getBlockState(block.up()).isOf(Blocks.WATER) && dontCullWater.isEnabled());
// renderizar
boolean shouldCull = !(onWater.getValue() && aboveState.isOf(Blocks.WATER) && dontCullWater.getValue());
RenderUtil.drawBlockFaceFilled(event.getMatrices(), block, Direction.UP, color, 0.001f, shouldCull);
}
}
private List<BlockPos> findExposedBlocks(int radius, int yRadius) {
List<BlockPos> results = new ArrayList<>();
private void updateBlocks() {
if (mc.player == null || mc.world == null) return;
BlockPos pos = mc.player.getBlockPos();
BlockPos playerPos = mc.player.getBlockPos();
int currentRadius = radius.getIntValue();
int currentYRadius = yRadius.getIntValue();
int minX = pos.getX() - radius;
int maxX = pos.getX() + radius;
int minY = Math.max(mc.world.getDimension().minY(), pos.getY() - yRadius);
int maxY = Math.min(mc.world.getDimension().height() - 1, pos.getY() + yRadius);
int minZ = pos.getZ() - radius;
int maxZ = pos.getZ() + radius;
// verificar si hace falta actualizar
boolean needsUpdate = fullRescanNeeded ||
lastRadius != currentRadius ||
lastYRadius != currentYRadius ||
(lastPlayerPos != null &&
playerPos.getSquaredDistance(lastPlayerPos) > (movementThreshold.getValue() * movementThreshold.getValue()));
maxY = Math.min(maxY, mc.world.getDimension().height() - 2);
if (!needsUpdate && incrementalUpdates.getValue() && incrementalLayer >= 0) {
// actualización incremental de una sola capa
performIncrementalUpdate(playerPos, currentRadius, currentYRadius);
return;
}
if (!needsUpdate) {
return;
}
lastPlayerPos = playerPos;
lastRadius = currentRadius;
lastYRadius = currentYRadius;
fullRescanNeeded = false;
incrementalLayer = 0;
// búsqueda
if (asyncSearch.getValue()) {
if (isSearching) return;
isSearching = true;
new Thread(() -> {
try {
performFullBlockSearch(playerPos, currentRadius, currentYRadius);
} finally {
isSearching = false;
}
}, "sputnik-lightoverlay-search").start();
} else {
performFullBlockSearch(playerPos, currentRadius, currentYRadius);
}
}
@SuppressWarnings("deprecation")
private void performFullBlockSearch(BlockPos center, int radius, int yRadius) {
Set<BlockPos> newBlocks = new HashSet<>();
int radiusSq = radius * radius;
int minY = Math.max(mc.world.getBottomY(), center.getY() - yRadius);
int maxY = Math.min(mc.world.getTopY(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, mc.player.getBlockPos()) - 1, center.getY() + yRadius);
for (int x = -radius; x <= radius; x++) {
for (int z = -radius; z <= radius; z++) {
if (x*x + z*z > radiusSq) continue;
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
for (int y = minY; y <= maxY; y++) {
BlockPos current = new BlockPos(x, y, z);
BlockPos pos = center.add(x, y - center.getY(), z);
if (!mc.world.isAir(current) && canSpawnOn(current))
results.add(current);
// nuh uh si el chunk no está cargado
if (!mc.world.isChunkLoaded(pos)) continue;
BlockState state = mc.world.getBlockState(pos);
BlockState aboveState = mc.world.getBlockState(pos.up());
if (isValidSpawnSurface(pos, state, aboveState)) {
newBlocks.add(pos.toImmutable());
}
}
}
}
return results;
// actualizar caché
cachedBlocks.clear();
cachedBlocks.addAll(newBlocks);
}
private boolean canSpawnOn(BlockPos pos) {
BlockState aboveState = mc.world.getBlockState(pos.up());
@SuppressWarnings("deprecation")
private void performIncrementalUpdate(BlockPos center, int radius, int yRadius) {
if (incrementalLayer > radius * 2) {
incrementalLayer = -radius;
}
int currentX = center.getX() - radius + incrementalLayer;
int radiusSq = radius * radius;
int minY = Math.max(mc.world.getBottomY(), center.getY() - yRadius);
int maxY = Math.min(mc.world.getTopY(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, mc.player.getBlockPos()) - 1, center.getY() + yRadius);
// buscar en una columna específica (x fijo, variar z)
for (int z = -radius; z <= radius; z++) {
int xDist = incrementalLayer;
if (xDist*xDist + z*z > radiusSq) continue;
for (int y = minY; y <= maxY; y++) {
BlockPos pos = new BlockPos(currentX, y, center.getZ() + z);
if (!mc.world.isChunkLoaded(pos)) continue;
BlockState state = mc.world.getBlockState(pos);
BlockState aboveState = mc.world.getBlockState(pos.up());
boolean isValid = isValidSpawnSurface(pos, state, aboveState);
if (isValid) {
cachedBlocks.add(pos.toImmutable());
} else {
cachedBlocks.remove(pos);
}
}
}
incrementalLayer++;
// cada 10 actualizaciones incrementales, hacer una limpieza de bloques lejanos
if (incrementalLayer % 10 == 0) {
cleanupDistantBlocks(center, radius);
}
}
private void cleanupDistantBlocks(BlockPos center, int radius) {
int radiusSq = radius * radius * 2;
Iterator<BlockPos> iterator = cachedBlocks.iterator();
while (iterator.hasNext()) {
BlockPos pos = iterator.next();
int dx = pos.getX() - center.getX();
int dz = pos.getZ() - center.getZ();
if (dx * dx + dz * dz > radiusSq) {
iterator.remove();
}
}
}
private boolean isValidSpawnSurface(BlockPos pos, BlockState state, BlockState aboveState) {
if (state.isAir() || !state.isOpaque() || !state.isFullCube(mc.world, pos)) {
return false;
}
Block aboveBlock = aboveState.getBlock();
if (aboveState.isAir()) return true;
if (aboveBlock == Blocks.WATER && onWater.isEnabled()) return true;
if (aboveBlock == Blocks.WATER && onWater.getValue()) return true;
if (aboveBlock instanceof PlantBlock) return true;
if (!aboveState.isOpaque() && !aboveState.isFullCube(mc.world, pos.up())) {
if (aboveBlock instanceof SlabBlock
|| aboveBlock instanceof StairsBlock
|| aboveBlock instanceof ButtonBlock
|| aboveBlock instanceof CarpetBlock
|| aboveBlock instanceof PressurePlateBlock
|| aboveBlock instanceof PaneBlock
|| aboveBlock instanceof TrapdoorBlock
|| aboveBlock instanceof FenceBlock
|| aboveBlock instanceof WallBlock
|| aboveBlock instanceof AnvilBlock
|| aboveBlock instanceof BedBlock) {
return false;
}
if (aboveBlock == Blocks.CHEST ||
aboveBlock == Blocks.ENDER_CHEST ||
aboveBlock == Blocks.BARREL ||
aboveBlock == Blocks.TRAPPED_CHEST) {
return false;
}
return aboveBlock != Blocks.ENCHANTING_TABLE
&& aboveBlock != Blocks.GRINDSTONE
&& aboveBlock != Blocks.STONECUTTER
&& aboveBlock != Blocks.LOOM
&& aboveBlock != Blocks.COMPOSTER
&& aboveBlock != Blocks.CAKE;
if (aboveBlock instanceof SlabBlock ||
aboveBlock instanceof StairsBlock ||
aboveBlock instanceof ButtonBlock ||
aboveBlock instanceof CarpetBlock ||
aboveBlock instanceof PressurePlateBlock ||
aboveBlock instanceof PaneBlock ||
aboveBlock instanceof TrapdoorBlock ||
aboveBlock instanceof FenceBlock ||
aboveBlock instanceof WallBlock ||
aboveBlock instanceof AnvilBlock ||
aboveBlock instanceof BedBlock) {
return false;
}
return true;
if (aboveBlock == Blocks.CHEST ||
aboveBlock == Blocks.ENDER_CHEST ||
aboveBlock == Blocks.BARREL ||
aboveBlock == Blocks.TRAPPED_CHEST ||
aboveBlock == Blocks.ENCHANTING_TABLE ||
aboveBlock == Blocks.GRINDSTONE ||
aboveBlock == Blocks.STONECUTTER ||
aboveBlock == Blocks.LOOM ||
aboveBlock == Blocks.COMPOSTER ||
aboveBlock == Blocks.CAKE) {
return false;
}
return !aboveState.isOpaque() || !aboveState.isFullCube(mc.world, pos.up());
}
}
}
@@ -25,7 +25,7 @@ public class NoMiningInterruptions extends Module {
if (entity == null || !isEnabled() || mc.player == null) return false;
boolean pickaxe = true;
if (withPickaxeOnly.isEnabled())
if (withPickaxeOnly.getValue())
pickaxe = (mc.player.getMainHandStack().isIn(ItemTags.PICKAXES)
|| mc.player.getOffHandStack().isIn(ItemTags.PICKAXES));
@@ -0,0 +1,167 @@
package me.retucio.sputnik.module.modules.world;
import me.retucio.sputnik.event.SubscribeEvent;
import me.retucio.sputnik.event.events.AddEntityEvent;
import me.retucio.sputnik.module.Category;
import me.retucio.sputnik.module.Module;
import me.retucio.sputnik.util.ChatUtil;
import me.retucio.sputnik.util.EntityUtil;
import net.minecraft.entity.EyeOfEnderEntity;
import net.minecraft.item.Items;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Hand;
import net.minecraft.util.math.Vec3d;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
// https://benwoodworth.com/minecraft/stronghold-calculator/index.js
public class StrongholdTriangulator extends Module {
public StrongholdTriangulator() {
super("triangulador de strongholds",
"usa josecadas para calcular la posición de la stronghold más cercana",
Category.WORLD);
}
private boolean firstEyeThrown;
private boolean secondEyeThrown;
private Vec3d a;
private Vec3d b;
private float alpha;
private float beta;
// usar un ejecutor retrasado para esperar a que el ojo de ender adquiera su ángulo
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
@Override
public void onEnable() {
super.onEnable();
ChatUtil.info("para empezar, lanza un ojo de ender");
ChatUtil.info("al lanzar los ojos, quédate quieto, o puede que la posición calculada salga errónea");
}
@Override
public void onDisable() {
reset();
scheduler.shutdown();
super.onDisable();
}
@Override
public void onTick() {
if (mc.player == null || mc.world == null) return;
if (firstEyeThrown && secondEyeThrown) {
StrongholdResult result = getIntersection();
if (result != null) {
if (result.errorMessage == null) {
ChatUtil.info(Text.literal("stronghold aproximadamente en: "
+ Formatting.GREEN
+ String.format("%.2f, %.2f", result.x, result.z)
+ Formatting.RESET
));
} else {
ChatUtil.error(result.errorMessage);
}
} else {
ChatUtil.error("upsi");
}
reset();
}
}
@SubscribeEvent
public void onAddEntity(AddEntityEvent event) {
if (mc.player == null || mc.world == null) return;
if (mc.player.getStackInHand(Hand.MAIN_HAND).getItem() != Items.ENDER_EYE) return;
if (event.getEntity() instanceof EyeOfEnderEntity eye) {
Vec3d throwPos = mc.player.getEntityPos();
int entityId = eye.getId();
scheduler.schedule(() -> {
// ejecutar en el hilo principal
mc.execute(() -> {
EyeOfEnderEntity currentEye = findEyeEntity(entityId);
if (currentEye != null) {
Vec3d eyeTargetPos = eye.getEntityPos();
if (eyeTargetPos != null) {
float yaw = (float) EntityUtil.getYaw(eyeTargetPos);
if (!firstEyeThrown) {
a = throwPos;
alpha = yaw;
firstEyeThrown = true;
ChatUtil.info("primer ojo registrado: "
+ String.format("%.1f, %.1f (%.1f°)", a.x, a.z, alpha));
ChatUtil.info("ahora muévete unos 200 bloques en una dirección distinta a la del ojo para lanzar el segundo");
ChatUtil.info("cuanta más distancia te separes, más preciso será el resultado");
} else if (!secondEyeThrown) {
b = throwPos;
beta = yaw;
secondEyeThrown = true;
ChatUtil.info("segundo ojo registrado: " +
String.format("%.1f, %.1f (%.1f°)", b.x, b.z, beta));
}
} else {
ChatUtil.error("upsi dupsi");
}
}
});
}, 1000, TimeUnit.MILLISECONDS); // esperar un segundo, a que el ojo adquiera velocidad
}
}
private EyeOfEnderEntity findEyeEntity(int entityId) {
if (mc.world == null) return null;
return (EyeOfEnderEntity) mc.world.getEntityById(entityId);
}
private StrongholdResult getIntersection() {
if (a == null || b == null) return null;
// obtener coordenadas y ángulos
double x0 = a.x;
double x1 = b.x;
double z0 = a.z;
double z1 = b.z;
double yaw0 = alpha / 180 * Math.PI;
double yaw1 = beta / 180 * Math.PI;
// distancia
double d0 = ((x1 - x0) + (z1 - z0) * Math.tan(yaw1)) / (Math.cos(yaw0) * Math.tan(yaw1) - Math.sin(yaw0));
double d1 = (d0 * Math.cos(yaw0) - (z1 - z0)) / Math.cos(yaw1);
// posición de la stronghold
double x = x0 - d0 * Math.sin(yaw0);
double z = z0 + d0 * Math.cos(yaw0);
// posibles casos
if (x0 == x1 && z0 == z1) { // ambos ojos lanzados desde la misma pos.
return new StrongholdResult(null, null, "pero muévete");
} else if (Double.isNaN(d0)) {
return new StrongholdResult(null, null, "los ojos forman líneas paralelas o coincidentes");
} else if (d0 < 0 || d1 < 0) {
return new StrongholdResult(null, null, "los ojos apuntan a strongholds distintas");
} else {
return new StrongholdResult(x, z, null);
}
}
private void reset() {
firstEyeThrown = false;
secondEyeThrown = false;
a = null;
b = null;
}
public record StrongholdResult(Double x, Double z, String errorMessage) {}
}
@@ -4,20 +4,29 @@ import me.retucio.sputnik.Sputnik;
import me.retucio.sputnik.event.events.sputnik.UpdateSettingEvent;
import me.retucio.sputnik.module.Module;
import java.util.function.Consumer;
// base para los tipos de ajustes
public abstract class Setting {
public abstract class Setting<T> {
private final String name;
private final String description;
protected final String name;
protected final String description;
private boolean visible = true;
private boolean searchMatch = true;
protected T value;
protected T defaultValue;
private SettingGroup sg;
protected Consumer<T> updateListener;
protected Setting(String name, String description) {
protected boolean visible = true;
protected boolean searchMatch = true;
protected SettingGroup sg;
protected Setting(String name, String description, T defaultValue) {
this.name = name;
this.description = description;
this.value = defaultValue;
this.defaultValue = defaultValue;
}
public boolean isVisible() {
@@ -44,6 +53,35 @@ public abstract class Setting {
return description;
}
public T getValue() {
return value;
}
public void setValue(T value) {
if (this.value != value) {
this.value = value;
fireUpdateEvent();
if (updateListener != null) {
updateListener.accept(value);
}
}
}
public T getDefaultValue() {
return defaultValue;
}
public void setDefaultValue(T value) {
if (this.defaultValue != value) {
this.defaultValue = value;
}
}
public void reset() {
setValue(defaultValue);
}
public SettingGroup getSg() {
return sg;
}
@@ -52,13 +90,17 @@ public abstract class Setting {
this.sg = sg;
}
public Module getModule() {
return this.sg.getModule();
}
public void fireUpdateEvent() {
Sputnik.EVENT_BUS.post(
new UpdateSettingEvent(
this,
sg.getModule()
.shouldSaveSettings()
)
);
new UpdateSettingEvent(this, getModule().shouldSaveSettings()));
}
public void onUpdate(Consumer<T> listener) {
this.updateListener = listener;
if (updateListener != null) updateListener.accept(value); // actualizar por primera vez
}
}
@@ -5,18 +5,17 @@ import me.retucio.sputnik.module.Module;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class SettingGroup implements Iterable<Setting> {
public class SettingGroup implements Iterable<Setting<?>> {
private Module module;
private final String name;
private boolean extended;
final List<Setting> settings = new ArrayList<>(1);
final List<Setting<?>> settings = new ArrayList<>(1);
public SettingGroup(String name, boolean extended) {
this.name = name;
@@ -24,31 +23,35 @@ public class SettingGroup implements Iterable<Setting> {
}
@Override
public @NotNull Iterator<Setting> iterator() {
public @NotNull Iterator<Setting<?>> iterator() {
return settings.iterator();
}
public <S extends Setting> S add(S setting) {
public <S extends Setting<?>> S add(S setting) {
setting.setSg(this);
settings.add(setting);
return setting;
}
@SafeVarargs
public final <S extends Setting> void addAll(S... ss) {
public final <S extends Setting<?>> void addAll(S... ss) {
for (S s : ss) {
add(s);
}
}
public Setting getSetting(String name) {
for (Setting setting : this)
public Setting<?> getSetting(String name) {
for (Setting<?> setting : this)
if (setting.getName().equals(name))
return setting;
return null;
}
public List<Setting<?>> getSettings() {
return settings;
}
public String getName() {
return name;
}
Loaded 100 of 162 files, more files were not shown because too many files have changed in this diff. Show more