v3.6
This commit is contained in:
1 parent
acecda3c0d
commit
412fe93a89
16 files changed
+582
-27
No files matched your search
+8
-4
@@ -4,15 +4,19 @@
|
||||
|
||||
### adiciones
|
||||
|
||||
#### comandos nuevos:
|
||||
|
||||
- repesperar: combinación de \$repetir y \$esperar
|
||||
|
||||
#### módulos nuevos:
|
||||
|
||||
- andamios: coloca bloques a tus pies a medida que caminas
|
||||
- cocaína: hace que todo vaya más rápido o más lento
|
||||
|
||||
### arreglos / mejoras
|
||||
|
||||
- arreglado el crash por no incluir el sistema de eventos en el mod (soy gilipollas)
|
||||
- mejoras varias al módulo tobillos fuertes
|
||||
- ahora el módulo de interfaces en portales funciona correctamente
|
||||
- reponer ya no está repe
|
||||
- opción para no romper el pico en selección de minado
|
||||
|
||||
## problemas reconocidos
|
||||
|
||||
- lo de siempre
|
||||
+1
-1
@@ -10,6 +10,6 @@ fabric_api_version=0.140.2+1.21.11
|
||||
|
||||
neutrino_version=1.1.0
|
||||
|
||||
mod_version=3.5
|
||||
mod_version=3.6
|
||||
maven_group=me.retucio
|
||||
archives_base_name=sputnik
|
||||
@@ -42,6 +42,7 @@ public class CommandManager {
|
||||
addCommand(new PrefixCommand());
|
||||
addCommand(new PurgeCommand());
|
||||
addCommand(new RepeatCommand());
|
||||
addCommand(new RepeatWaitCommand());
|
||||
addCommand(new SaveScreenshotCommand());
|
||||
addCommand(new SendCommand());
|
||||
addCommand(new SpectateCommand());
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package me.retucio.sputnik.command.commands;
|
||||
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import me.retucio.sputnik.command.Command;
|
||||
import me.retucio.sputnik.util.ChatUtil;
|
||||
import net.minecraft.command.CommandSource;
|
||||
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class RepeatWaitCommand extends Command {
|
||||
|
||||
public RepeatWaitCommand() {
|
||||
super("repesperar", "combinación de $repetir y $esperar");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(LiteralArgumentBuilder<CommandSource> builder) {
|
||||
builder.then(argument("ms", IntegerArgumentType.integer(1))
|
||||
.then(argument("veces", IntegerArgumentType.integer(1))
|
||||
.then(argument("comando", StringArgumentType.greedyString())
|
||||
.executes((context) -> {
|
||||
int ms = context.getArgument("ms", Integer.class);
|
||||
int times = context.getArgument("veces", Integer.class);
|
||||
String cmd = context.getArgument("comando", String.class);
|
||||
|
||||
for (int i = 0; i < times; i++) {
|
||||
int delay = i * ms;
|
||||
int finalI = i;
|
||||
new ScheduledThreadPoolExecutor(2).schedule(
|
||||
() -> ChatUtil.info(
|
||||
cmd.replaceAll("(?i)%index%",
|
||||
String.valueOf(finalI))),
|
||||
delay,
|
||||
TimeUnit.MILLISECONDS
|
||||
);
|
||||
}
|
||||
return SUCCESS;
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package me.retucio.sputnik.event.input;
|
||||
|
||||
import com.github.retucio.neutrino.Event;
|
||||
|
||||
public class SneakEvent extends Event {}
|
||||
@@ -0,0 +1,19 @@
|
||||
package me.retucio.sputnik.mixin.mixins.player;
|
||||
|
||||
import me.retucio.sputnik.Sputnik;
|
||||
import me.retucio.sputnik.event.input.SneakEvent;
|
||||
import net.minecraft.util.PlayerInput;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(PlayerInput.class)
|
||||
public abstract class PlayerInputMixin {
|
||||
|
||||
@Inject(method = "sneak", at = @At("HEAD"), cancellable = true)
|
||||
private void onSneak(CallbackInfoReturnable<Boolean> cir) {
|
||||
SneakEvent event = Sputnik.EVENT_BUS.post(new SneakEvent());
|
||||
if (event.isCancelled()) cir.cancel();
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package me.retucio.sputnik.mixin.mixins.world;
|
||||
|
||||
import me.retucio.sputnik.module.ModuleManager;
|
||||
import me.retucio.sputnik.module.modules.world.Timer;
|
||||
import net.minecraft.client.render.RenderTickCounter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
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(RenderTickCounter.Dynamic.class)
|
||||
public abstract class RenderTickCounterDynamicMixin {
|
||||
|
||||
@Shadow
|
||||
private float dynamicDeltaTicks;
|
||||
|
||||
@Inject(method = "beginRenderTick(J)I", at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/RenderTickCounter$Dynamic;lastTimeMillis:J", opcode = Opcodes.PUTFIELD))
|
||||
private void onBeingRenderTick(long timeMillis, CallbackInfoReturnable<Integer> cir) {
|
||||
dynamicDeltaTicks *= ModuleManager.INSTANCE.getModuleByClass(Timer.class).multiplier.getFloatValue();
|
||||
}
|
||||
}
|
||||
@@ -116,6 +116,7 @@ public class ModuleManager {
|
||||
add(new Jesus());
|
||||
add(new ReverseStep());
|
||||
add(new SafeWalk());
|
||||
add(new Scaffold());
|
||||
add(new Slippy());
|
||||
add(new Step());
|
||||
add(new TridentBoost());
|
||||
@@ -171,6 +172,7 @@ public class ModuleManager {
|
||||
add(new Racist());
|
||||
add(new StrongholdTriangulator());
|
||||
add(new TimeChanger());
|
||||
add(new Timer());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,339 @@
|
||||
package me.retucio.sputnik.module.modules.movement;
|
||||
|
||||
import com.github.retucio.neutrino.EventListener;
|
||||
import com.google.common.collect.Streams;
|
||||
import me.retucio.sputnik.event.input.SneakEvent;
|
||||
import me.retucio.sputnik.event.interact.PlaceBlockEvent;
|
||||
import me.retucio.sputnik.event.render.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.*;
|
||||
|
||||
import me.retucio.sputnik.util.Colors;
|
||||
import me.retucio.sputnik.util.InventoryUtil;
|
||||
import me.retucio.sputnik.util.Lists;
|
||||
import me.retucio.sputnik.util.NetworkUtil;
|
||||
import me.retucio.sputnik.util.render.RenderUtil;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.FallingBlock;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Scaffold extends Module {
|
||||
|
||||
private final SettingGroup sgBlocks = addSg(new SettingGroup("bloques", false));
|
||||
private final SettingGroup sgBridge = addSg(new SettingGroup("puente", true));
|
||||
private final SettingGroup sgRender = addSg(new SettingGroup("render", false));
|
||||
|
||||
// todo: arreglar esta puta mierda
|
||||
private final BooleanSetting rotate = sgGeneral.add(new BooleanSetting(
|
||||
"rotar",
|
||||
"mover la cabeza",
|
||||
false
|
||||
));
|
||||
|
||||
|
||||
/* ajustes de selección de bloques */
|
||||
|
||||
private final ListSetting<Block> blocks = sgBlocks.add(new ListSetting<>(
|
||||
"bloques",
|
||||
"bloques a aplicar al filtro",
|
||||
Lists.blockList,
|
||||
Lists.allFalse(Lists.blockList),
|
||||
Lists.blockNames
|
||||
));
|
||||
|
||||
private final EnumSetting<ListMode> blocksFilter = sgBlocks.add(new EnumSetting<>(
|
||||
"filtro",
|
||||
"tipo de filtro a usar",
|
||||
ListMode.class, ListMode.BLACKLIST
|
||||
));
|
||||
|
||||
private final BooleanSetting autoSelectItem = sgBlocks.add(new BooleanSetting(
|
||||
"autoselect",
|
||||
"seleccionar slot más cercano con bloques automáticamente",
|
||||
true
|
||||
));
|
||||
|
||||
|
||||
/* extender puente */
|
||||
|
||||
private final BooleanSetting extend = sgBridge.add(new BooleanSetting(
|
||||
"extender",
|
||||
"poner bloques en frente al caminar",
|
||||
false
|
||||
));
|
||||
|
||||
private final NumberSetting extendDistance = sgBridge.add(new NumberSetting(
|
||||
"distancia a extender",
|
||||
"cuánto extender",
|
||||
2,
|
||||
0,
|
||||
4,
|
||||
0.1
|
||||
));
|
||||
|
||||
|
||||
/* torre */
|
||||
|
||||
private final BooleanSetting tower = sgBridge.add(new BooleanSetting(
|
||||
"torre",
|
||||
"hacer torres verticales chulas",
|
||||
false
|
||||
));
|
||||
|
||||
private final NumberSetting towerSpeed = sgBridge.add(new NumberSetting(
|
||||
"velocidad de torre",
|
||||
"a qué velocidad hacer la torre",
|
||||
0.5,
|
||||
0,
|
||||
1,
|
||||
0.01
|
||||
));
|
||||
|
||||
private final BooleanSetting towerWhileMoving = sgBridge.add(new BooleanSetting(
|
||||
"torre moviéndose",
|
||||
"te permite hacer una torre mientras te mueves",
|
||||
false
|
||||
));
|
||||
|
||||
|
||||
/* otros */
|
||||
|
||||
private final BooleanSetting mjBridge = sgBridge.add(new BooleanSetting(
|
||||
"mj bridge",
|
||||
"hacer que saltar no eleve el nivel y del puente",
|
||||
false
|
||||
));
|
||||
|
||||
private final BooleanSetting sneakForDown = sgBridge.add(new BooleanSetting(
|
||||
"descender",
|
||||
"agacharse para descender",
|
||||
true
|
||||
));
|
||||
|
||||
private final BooleanSetting headhitter = sgBridge.add(new BooleanSetting(
|
||||
"headhitter",
|
||||
"poner bloques sobre tu cabeza",
|
||||
false
|
||||
));
|
||||
|
||||
|
||||
/* ajustes de renderizado */
|
||||
|
||||
private final BooleanSetting outlines = sgRender.add(new BooleanSetting(
|
||||
"contorno",
|
||||
"renderizar contorno del bloque colocado",
|
||||
true
|
||||
));
|
||||
|
||||
private final ColorSetting outlineColor = sgRender.add(new ColorSetting(
|
||||
"color del contorno",
|
||||
"color a usar al renderizar el contorno",
|
||||
Colors.mainColor,
|
||||
false
|
||||
));
|
||||
|
||||
private final NumberSetting lineWidth = sgRender.add(new NumberSetting(
|
||||
"grosor de línea",
|
||||
"grosor de línea del contorno",
|
||||
1.5,
|
||||
0.1,
|
||||
10,
|
||||
0.1
|
||||
));
|
||||
|
||||
private final BooleanSetting fillings = sgRender.add(new BooleanSetting(
|
||||
"relleno",
|
||||
"renderizar relleno del bloque colocado",
|
||||
false
|
||||
));
|
||||
|
||||
private final ColorSetting fillingColor = sgRender.add(new ColorSetting(
|
||||
"color del relleno",
|
||||
"color a uisar al renderizar el relleno",
|
||||
Colors.withAlpha(Colors.mainColor, 60),
|
||||
false
|
||||
));
|
||||
|
||||
|
||||
private final BlockPos.Mutable bp = new BlockPos.Mutable();
|
||||
private Integer mjY = null;
|
||||
|
||||
|
||||
public Scaffold() {
|
||||
super("andamios", "pone bloques bajo tus pies de manera automática", Category.MOVEMENT);
|
||||
|
||||
extend.onUpdate(extendDistance::setVisible);
|
||||
|
||||
tower.onUpdate(v -> {
|
||||
towerSpeed.setVisible(v);
|
||||
towerWhileMoving.setVisible(v);
|
||||
});
|
||||
|
||||
outlines.onUpdate(v -> {
|
||||
outlineColor.setVisible(v);
|
||||
lineWidth.setVisible(v);
|
||||
});
|
||||
|
||||
fillings.onUpdate(fillingColor::setVisible);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
mjY = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick() {
|
||||
if (mc.player == null || mc.world == null) return;
|
||||
|
||||
Vec3d pos = mc.player.getEntityPos();
|
||||
|
||||
// extender puente si se está moviendo hacia adelante
|
||||
if (extend.getValue() && isMoving() && mc.player.forwardSpeed > 0) {
|
||||
Vec3d dir = Vec3d.fromPolar(0, mc.player.getYaw()).normalize().multiply(extendDistance.getValue());
|
||||
pos = pos.add(dir.x, 0, dir.z);
|
||||
}
|
||||
|
||||
// seleccionar nivel Y
|
||||
double y;
|
||||
if (mjBridge.getValue() && mjY != null && isMoving()) {
|
||||
y = mjY;
|
||||
} else {
|
||||
y = pos.y - 0.5;
|
||||
}
|
||||
|
||||
// descender con la tecla de agacharse
|
||||
if (sneakForDown.getValue() && mc.options.sneakKey.isPressed()) {
|
||||
if (mc.world.isAir(bp.withY(bp.getY() - 1))) {
|
||||
y -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// colocar bloque
|
||||
bp.set(pos.x, y, pos.z);
|
||||
place(bp);
|
||||
|
||||
// colocar bloque encima de la cabeza
|
||||
if (headhitter.getValue() && mc.options.jumpKey.isPressed() && !mc.options.sneakKey.isPressed()) {
|
||||
place(mc.player.getBlockPos().up(2));
|
||||
}
|
||||
|
||||
// poner bloques a los pies del jugador mientras asciende para hacer la torre
|
||||
if (tower.getValue()
|
||||
&& mc.options.jumpKey.isPressed()
|
||||
&& !mc.options.sneakKey.isPressed()
|
||||
&& !mc.player.getInventory().getSelectedStack().isEmpty()
|
||||
&& !mc.world.isAir(mc.player.getBlockPos().down())) {
|
||||
Vec3d velocity = mc.player.getVelocity();
|
||||
Box playerBox = mc.player.getBoundingBox();
|
||||
|
||||
if (Streams.stream(mc.world.getBlockCollisions(mc.player, playerBox.offset(0, 1, 0))).toList().isEmpty()) {
|
||||
if (towerWhileMoving.getValue() || !isMoving()) {
|
||||
velocity = new Vec3d(velocity.x, towerSpeed.getValue(), velocity.z);
|
||||
}
|
||||
mc.player.setVelocity(velocity);
|
||||
} else {
|
||||
mc.player.setVelocity(velocity.x, Math.ceil(mc.player.getY()) - mc.player.getY(), velocity.z);
|
||||
mc.player.setOnGround(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventListener
|
||||
private void onRenderWorld(Render3DEvent event) {
|
||||
if (outlines.getValue()) RenderUtil.drawBlockOutline(event.getMatrices(), bp, outlineColor.getValue(), lineWidth.getFloatValue(), false);
|
||||
if (fillings.getValue()) RenderUtil.drawBlockFilled(event.getMatrices(), bp, fillingColor.getValue(), false);
|
||||
}
|
||||
|
||||
@EventListener
|
||||
private void onPlaceBlock(PlaceBlockEvent event) {
|
||||
// guardar último valor Y para el mj bridge
|
||||
if (mjBridge.getValue()) {
|
||||
mjY = event.getResult().getBlockPos().getY();
|
||||
}
|
||||
}
|
||||
|
||||
@EventListener
|
||||
private void onSneak(SneakEvent event) {
|
||||
// no agacharse
|
||||
if (sneakForDown.getValue()) {
|
||||
event.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void place(BlockPos pos) {
|
||||
int slot = -1;
|
||||
// seleccionar bloque
|
||||
if (autoSelectItem.getValue()) {
|
||||
List<Integer> slots = InventoryUtil.findAllSlots(this::isValidBlock);
|
||||
for (int s : slots) {
|
||||
if (PlayerInventory.isValidHotbarIndex(s)) {
|
||||
slot = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (slot == -1) return;
|
||||
} else {
|
||||
slot = mc.player.getInventory().getSelectedSlot();
|
||||
}
|
||||
|
||||
if (mc.player.getInventory().getSelectedSlot() != slot) {
|
||||
mc.player.getInventory().setSelectedSlot(slot);
|
||||
}
|
||||
|
||||
// colocar bloque
|
||||
NetworkUtil.placeBlock(
|
||||
pos, Hand.MAIN_HAND,
|
||||
mc.player.getInventory().getSelectedSlot(),
|
||||
rotate.getValue(),
|
||||
false,
|
||||
true,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
// método helper para ver si un bloque cumple con el filtro
|
||||
private boolean isValidBlock(ItemStack stack) {
|
||||
if (!(stack.getItem() instanceof BlockItem)) return false;
|
||||
Block block = ((BlockItem) stack.getItem()).getBlock();
|
||||
|
||||
boolean contains = blocks.isEnabled(block);
|
||||
if (blocksFilter.is(ListMode.BLACKLIST) && contains) return false;
|
||||
if (blocksFilter.is(ListMode.WHITELIST) && !contains) return false;
|
||||
|
||||
if (!Block.isShapeFullCube(block.getDefaultState().getCollisionShape(mc.world, BlockPos.ORIGIN))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (block instanceof FallingBlock) {
|
||||
return !FallingBlock.canFallThrough(mc.world.getBlockState(mc.player.getBlockPos().down()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isMoving() {
|
||||
return mc.player.forwardSpeed != 0
|
||||
|| mc.player.sidewaysSpeed != 0;
|
||||
}
|
||||
|
||||
public enum ListMode {
|
||||
WHITELIST("lista blanca (incluir)"),
|
||||
BLACKLIST("lista negra (excluir");
|
||||
|
||||
private final String name;
|
||||
ListMode(String name) { this.name = name; }
|
||||
@Override public String toString() { return name; }
|
||||
}
|
||||
}
|
||||
@@ -88,6 +88,12 @@ public class PacketMine extends Module {
|
||||
0.1
|
||||
));
|
||||
|
||||
private final BooleanSetting dontBreak = sgGeneral.add(new BooleanSetting(
|
||||
"no romper",
|
||||
"evita romper el pico",
|
||||
true
|
||||
));
|
||||
|
||||
public PacketMine() {
|
||||
super("selección de minado",
|
||||
"selecciona bloques a minar con paquetes",
|
||||
@@ -150,7 +156,9 @@ public class PacketMine extends Module {
|
||||
currentOrderIndex = (currentOrderIndex + 1) % miningBlocks.size();
|
||||
break;
|
||||
}
|
||||
currentOrderIndex = (currentOrderIndex + 1) % miningBlocks.size();
|
||||
if (!miningBlocks.isEmpty()) {
|
||||
currentOrderIndex = (currentOrderIndex + 1) % miningBlocks.size();
|
||||
}
|
||||
} while (currentOrderIndex != startIndex);
|
||||
|
||||
if (!processed) {
|
||||
@@ -252,6 +260,12 @@ public class PacketMine extends Module {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dontBreak.getValue() && mc.player.getMainHandStack().getMaxDamage() - mc.player.getMainHandStack().getDamage() <= 1) {
|
||||
ChatUtil.warn("pico por romperse");
|
||||
toggle();
|
||||
return false;
|
||||
}
|
||||
|
||||
mc.interactionManager.sendSequencedPacket(mc.world, sequence ->
|
||||
new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.START_DESTROY_BLOCK, pos, dir, sequence));
|
||||
mining = true;
|
||||
|
||||
@@ -143,7 +143,7 @@ public class AutoFish extends Module {
|
||||
|
||||
private int switchToFishingRod() {
|
||||
if (mc.player.getActiveItem().isOf(Items.FISHING_ROD)) return mc.player.getInventory().getSelectedSlot();
|
||||
List<Integer> slots = InventoryUtil.findItem(Items.FISHING_ROD);
|
||||
List<Integer> slots = InventoryUtil.findAllSlots(stack -> stack.isOf(Items.FISHING_ROD));
|
||||
for (int slot : slots) {
|
||||
if (PlayerInventory.isValidHotbarIndex(slot)) {
|
||||
mc.player.getInventory().setSelectedSlot(slot);
|
||||
|
||||
@@ -163,7 +163,7 @@ public class AutoTool extends Module {
|
||||
if (result.getType() == HitResult.Type.MISS || !(result instanceof BlockHitResult bhr)) return;
|
||||
BlockState state = mc.world.getBlockState(bhr.getBlockPos());
|
||||
|
||||
List<ItemStack> tools = InventoryUtil.getStacksOfComponentType(DataComponentTypes.TOOL);
|
||||
List<ItemStack> tools = InventoryUtil.find(DataComponentTypes.TOOL);
|
||||
if (tools.isEmpty()) return;
|
||||
|
||||
Map<Float, ItemStack> speeds = new HashMap<>();
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package me.retucio.sputnik.module.modules.world;
|
||||
|
||||
import me.retucio.sputnik.module.Category;
|
||||
import me.retucio.sputnik.module.Module;
|
||||
import me.retucio.sputnik.module.setting.settings.NumberSetting;
|
||||
|
||||
public class Timer extends Module {
|
||||
|
||||
public NumberSetting multiplier = sgGeneral.add(new NumberSetting(
|
||||
"multi",
|
||||
"como en el Balatro",
|
||||
1,
|
||||
0.1,
|
||||
10,
|
||||
0.1
|
||||
));
|
||||
|
||||
public Timer() {
|
||||
super("cocaína", "cambia la velocidad de todo el en juego", Category.WORLD);
|
||||
}
|
||||
}
|
||||
@@ -70,7 +70,20 @@ public class InventoryUtil {
|
||||
return stacks;
|
||||
}
|
||||
|
||||
public static List<ItemStack> getStacksOfTag(TagKey<Item> tag) {
|
||||
public static List<Integer> findAllSlots(Predicate<ItemStack> predicate) {
|
||||
List<Integer> slots = new ArrayList<>();
|
||||
if (mc.player == null) return slots;
|
||||
for (int i = 0; i < mc.player.getInventory().size(); i++) {
|
||||
ItemStack stack = mc.player.getInventory().getStack(i);
|
||||
if (predicate.test(stack)) {
|
||||
slots.add(i);
|
||||
}
|
||||
}
|
||||
return slots;
|
||||
}
|
||||
|
||||
|
||||
public static List<ItemStack> find(TagKey<Item> tag) {
|
||||
if (mc.player == null) return null;
|
||||
List<ItemStack> stacks = new ArrayList<>();
|
||||
for (ItemStack stack : mc.player.getInventory()) {
|
||||
@@ -83,7 +96,7 @@ public class InventoryUtil {
|
||||
return stacks;
|
||||
}
|
||||
|
||||
public static List<ItemStack> getStacksOfComponentType(ComponentType<?> componentType) {
|
||||
public static List<ItemStack> find(ComponentType<?> componentType) {
|
||||
List<ItemStack> stacks = new ArrayList<>();
|
||||
if (mc.player == null) return stacks;
|
||||
for (ItemStack stack : mc.player.getInventory()) {
|
||||
@@ -256,20 +269,6 @@ public class InventoryUtil {
|
||||
return matchingSlots;
|
||||
}
|
||||
|
||||
public static List<Integer> findItem(Item item) {
|
||||
List<Integer> matchingSlots = new ArrayList<>();
|
||||
PlayerInventory inv = mc.player.getInventory();
|
||||
|
||||
for (int i = 0; i < inv.size(); i++) {
|
||||
ItemStack stack = inv.getStack(i);
|
||||
if (!stack.isEmpty() && stack.isOf(item)) {
|
||||
matchingSlots.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
return matchingSlots;
|
||||
}
|
||||
|
||||
public static void quickMoveAll(HandledScreen<?> screen, ItemStack reference) {
|
||||
if (mc.player == null || mc.interactionManager == null) return;
|
||||
|
||||
@@ -349,6 +348,4 @@ public class InventoryUtil {
|
||||
public static Inventory getEchestInv() {
|
||||
return echestInv;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -2,15 +2,27 @@ package me.retucio.sputnik.util;
|
||||
|
||||
|
||||
import me.retucio.sputnik.event.network.PacketEvent;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.command.argument.EntityAnchorArgumentType;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import net.minecraft.network.listener.PacketListener;
|
||||
import net.minecraft.network.packet.Packet;
|
||||
import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket;
|
||||
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
|
||||
import net.minecraft.network.packet.s2c.play.WorldTimeUpdateS2CPacket;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -87,4 +99,74 @@ public class NetworkUtil {
|
||||
|
||||
mc.player.setSneaking(wasSneaking);
|
||||
}
|
||||
|
||||
public static boolean placeBlock(BlockPos blockPos, Hand hand, int slot, boolean rotate, boolean swingHand, boolean checkEntities, boolean swapBack) {
|
||||
if (slot < 0 || slot > 8) return false;
|
||||
|
||||
Block toPlace = Blocks.OBSIDIAN;
|
||||
ItemStack i = hand == Hand.MAIN_HAND ? mc.player.getInventory().getStack(slot) : mc.player.getOffHandStack();
|
||||
if (i.getItem() instanceof BlockItem blockItem) toPlace = blockItem.getBlock();
|
||||
if (!canPlaceBlock(blockPos, checkEntities, toPlace)) return false;
|
||||
|
||||
Vec3d hitPos = Vec3d.ofCenter(blockPos);
|
||||
|
||||
BlockPos neighbour;
|
||||
Direction side = getClosestSide(blockPos);
|
||||
|
||||
if (side == null) {
|
||||
side = Direction.UP;
|
||||
neighbour = blockPos;
|
||||
} else {
|
||||
neighbour = blockPos.offset(side);
|
||||
hitPos = hitPos.add(side.getOffsetX() * 0.5, side.getOffsetY() * 0.5, side.getOffsetZ() * 0.5);
|
||||
}
|
||||
|
||||
BlockHitResult bhr = new BlockHitResult(hitPos, side.getOpposite(), neighbour, false);
|
||||
|
||||
int prevSlot = mc.player.getInventory().getSelectedSlot();
|
||||
|
||||
if (rotate) {
|
||||
mc.player.setYaw((float) EntityUtil.getYaw(hitPos));
|
||||
mc.player.setPitch((float) EntityUtil.getPitch(hitPos));
|
||||
}
|
||||
|
||||
InventoryUtil.swapWithHotbar(mc.player.getInventory().getSelectedSlot(), slot);
|
||||
interactBlock(bhr, hand, swingHand);
|
||||
|
||||
if (swapBack) {
|
||||
InventoryUtil.swapWithHotbar(mc.player.getInventory().getSelectedSlot(), prevSlot);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean canPlaceBlock(BlockPos blockPos, boolean checkEntities, Block block) {
|
||||
if (blockPos == null) return false;
|
||||
if (!World.isValid(blockPos)) return false;
|
||||
if (!mc.world.getBlockState(blockPos).isReplaceable()) return false;
|
||||
return !checkEntities || mc.world.canPlace(block.getDefaultState(), blockPos, ShapeContext.absent());
|
||||
}
|
||||
|
||||
public static Direction getClosestSide(BlockPos blockPos) {
|
||||
Vec3d lookVec = blockPos.toCenterPos().subtract(mc.player.getEyePos());
|
||||
double bestRelevancy = -Double.MAX_VALUE;
|
||||
Direction bestSide = null;
|
||||
|
||||
for (Direction side : Direction.values()) {
|
||||
BlockPos neighbor = blockPos.offset(side);
|
||||
BlockState state = mc.world.getBlockState(neighbor);
|
||||
|
||||
if (state.isAir()) continue;
|
||||
|
||||
if (!state.getFluidState().isEmpty()) continue;
|
||||
|
||||
double relevancy = side.getAxis().choose(lookVec.getX(), lookVec.getY(), lookVec.getZ()) * side.getDirection().offset();
|
||||
if (relevancy > bestRelevancy) {
|
||||
bestRelevancy = relevancy;
|
||||
bestSide = side;
|
||||
}
|
||||
}
|
||||
|
||||
return bestSide;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
"mixins.network.ServerConnectorMixin",
|
||||
"mixins.network.YggdrasilUserApiServiceMixin",
|
||||
"mixins.player.PlayerEntityMixin",
|
||||
"mixins.player.PlayerInputMixin",
|
||||
"mixins.player.PlayerInventoryMixin",
|
||||
"mixins.world.BlockCollisionSpliteratorMixin"
|
||||
],
|
||||
@@ -96,6 +97,7 @@
|
||||
"mixins.world.DamageParticleFactoryMixin",
|
||||
"mixins.world.DamageParticleMixin",
|
||||
"mixins.world.EmitterParticleMixin",
|
||||
"mixins.world.ParticleManagerMixin"
|
||||
"mixins.world.ParticleManagerMixin",
|
||||
"mixins.world.RenderTickCounterDynamicMixin"
|
||||
]
|
||||
}
|
||||
Reference in new issue
Block a user