Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81fc25c33d |
No files matched your search
+6
-2
@@ -1,4 +1,4 @@
|
||||
# v5.4.1
|
||||
# v5.5
|
||||
|
||||
## novedades
|
||||
|
||||
@@ -6,9 +6,13 @@
|
||||
|
||||
#### módulos nuevos:
|
||||
|
||||
#### comandos nuevos:
|
||||
|
||||
- `$panorama`: construye un pack de texturas con una panorámica basada en tu posición actual.
|
||||
|
||||
### arreglos / mejoras
|
||||
|
||||
- actualizado todos los links a GitHub para reflejar la migración a Codeberg.
|
||||
- arreglado ScreenshotMixin, es decir, que ya no crasheará al tomar capturas
|
||||
|
||||
## problemas reconocidos
|
||||
|
||||
|
||||
+3
-1
@@ -10,6 +10,8 @@ elytra-recast: https://github.com/InLieuOfLuna/elytra-recast/
|
||||
SpearHax: https://github.com/etianl/spearHax/
|
||||
ProjectileTrajectoryPreview: https://github.com/maDU59/ProjectilesTrajectoryPreview
|
||||
DupersUnited public addon: https://discord.gg/dupes | https://dupers.wtf
|
||||
Stardust: https://github.com/0xTas/stardust/
|
||||
|
||||
probablemente más pero como tengo demencia se me olvida
|
||||
si quieres que te acredite o quite tu código de mi mod, mándame un mensaje en discord (username: retucio) y sin problemas :)
|
||||
si quieres que te acredite o quite tu código de mi mod, mándame un mensaje en discord (username: retucio) y sin problemas :)
|
||||
también es probable que haya créditos sueltos en forma de comentarios donde haya usado código ajeno
|
||||
+1
-1
@@ -10,6 +10,6 @@ discord_rpc_version=1.0.3
|
||||
neutrino_version=1.1.0
|
||||
jdk_version=25
|
||||
|
||||
mod_version=5.4
|
||||
mod_version=5.5
|
||||
maven_group=me.retucio
|
||||
archives_base_name=sputnik
|
||||
@@ -38,6 +38,7 @@ public class CommandManager {
|
||||
addCommand(new EnderChestCommand());
|
||||
addCommand(new FriendCommand());
|
||||
addCommand(new GarbageCleanerCommand());
|
||||
addCommand(new PanoramaCommand());
|
||||
addCommand(new PeekCommand());
|
||||
addCommand(new PluginsCommand());
|
||||
addCommand(new PrefixCommand());
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
package me.retucio.sputnik.command.commands;
|
||||
|
||||
|
||||
import com.github.retucio.neutrino.EventListener;
|
||||
import me.retucio.sputnik.Sputnik;
|
||||
import me.retucio.sputnik.command.Command;
|
||||
import me.retucio.sputnik.event.TickEvent;
|
||||
import me.retucio.sputnik.util.ChatUtil;
|
||||
import me.retucio.sputnik.util.MiscUtil;
|
||||
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.WorldVersion;
|
||||
import net.minecraft.client.Screenshot;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraft.server.packs.metadata.pack.PackFormat;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
|
||||
/**
|
||||
* literalmente robado de <a href="https://github.com/0xTas/stardust/blob/main/src/main/java/dev/stardust/commands/Panorama.java">aquí</a>
|
||||
*/
|
||||
|
||||
public class PanoramaCommand extends Command {
|
||||
|
||||
private int i = -1;
|
||||
int timer = 10;
|
||||
|
||||
boolean ready = false;
|
||||
boolean warming = false;
|
||||
|
||||
private float prevYaw;
|
||||
private float prevPitch;
|
||||
|
||||
private int prevWidth;
|
||||
private int prevHeight;
|
||||
|
||||
private boolean prevHudHidden;
|
||||
|
||||
@Nullable Path dir = null;
|
||||
|
||||
public PanoramaCommand() {
|
||||
super("panorama", Component.translatable("sputnik.commands.panorama.desc").getString());
|
||||
}
|
||||
|
||||
private void takeScreenshot() {
|
||||
if (dir == null) return;
|
||||
|
||||
Screenshot.grab(
|
||||
dir.toFile(),
|
||||
"panorama_" + i + ".png",
|
||||
mc.gameRenderer.mainRenderTarget(),
|
||||
1, msg -> Sputnik.LOGGER.info(msg.getString())
|
||||
);
|
||||
|
||||
i++;
|
||||
warming = false;
|
||||
}
|
||||
|
||||
private void begin(String name) {
|
||||
if (mc.player == null) return;
|
||||
|
||||
dir = FabricLoader.getInstance().getGameDir().resolve(Sputnik.MOD_ID + "/panoramas/" + name);
|
||||
dir.toFile().mkdirs();
|
||||
|
||||
i = 0;
|
||||
warming = false;
|
||||
|
||||
prevYaw = mc.player.getYRot();
|
||||
prevPitch = mc.player.getXRot();
|
||||
prevWidth = mc.getWindow().getWidth();
|
||||
prevHeight = mc.getWindow().getHeight();
|
||||
prevHudHidden = mc.gui.hud.isHidden();
|
||||
|
||||
mc.getWindow().setWidth(4096);
|
||||
mc.getWindow().setHeight(4096);
|
||||
mc.gameRenderer.mainRenderTarget().resize(4096, 4096);
|
||||
}
|
||||
|
||||
private void assembleResourcePack() {
|
||||
if (dir == null) return;
|
||||
|
||||
Path resourcePacks = FabricLoader.getInstance().getGameDir().resolve("resourcepacks");
|
||||
Path screenshotsFolder = FabricLoader.getInstance().getGameDir().resolve(Sputnik.MOD_ID + "/panoramas/" + dir.getFileName() + "/screenshots");
|
||||
Path customBaseFolder = resourcePacks.resolve(dir.getFileName());
|
||||
Path customPackFolder = customBaseFolder.resolve("assets/minecraft/textures/gui/title/background/");
|
||||
customPackFolder.toFile().mkdirs();
|
||||
|
||||
String mcMeta =
|
||||
"""
|
||||
{
|
||||
"pack":
|
||||
{
|
||||
"min_format": [65, 0],
|
||||
"max_format": [%d, 0],
|
||||
"description": "%s"
|
||||
}
|
||||
}
|
||||
""".formatted(
|
||||
getPackVersion(),
|
||||
Component.translatable("sputnik.commands.panorama.packdesc").getString()
|
||||
);
|
||||
|
||||
try {
|
||||
int luckyNumber = ThreadLocalRandom.current().nextInt(6);
|
||||
Files.walkFileTree(screenshotsFolder, new SimpleFileVisitor<>() {
|
||||
public @NonNull FileVisitResult visitFile(@NonNull Path file, @NonNull BasicFileAttributes attrs) {
|
||||
MiscUtil.copy(file.toFile(), customPackFolder.resolve(file.getFileName()).toFile());
|
||||
|
||||
// pack.png random de alguna de los screenshots
|
||||
if (file.getFileName().toString().contains(String.valueOf(luckyNumber))) {
|
||||
MiscUtil.copy(file.toFile(), customBaseFolder.resolve("pack.png").toFile());
|
||||
}
|
||||
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
|
||||
File packMeta = customBaseFolder.resolve("pack.mcmeta").toFile();
|
||||
if (!packMeta.createNewFile()) {
|
||||
ChatUtil.error(Component.translatable("sputnik.commands.panorama.errorassemble").getString());
|
||||
return;
|
||||
}
|
||||
Files.write(packMeta.toPath(), mcMeta.getBytes());
|
||||
|
||||
// eliminar el efecto vignette feo de cojones que usa Minecraft por defecto
|
||||
BufferedImage transparentOverlay = new BufferedImage(16, 128, BufferedImage.TYPE_INT_ARGB);
|
||||
File overlayImage = customPackFolder.resolve("panorama_overlay.png").toFile();
|
||||
ImageIO.write(transparentOverlay, "PNG", overlayImage);
|
||||
} catch (Exception e) {
|
||||
ChatUtil.error("error de i/o");
|
||||
Sputnik.LOGGER.error(e);
|
||||
}
|
||||
|
||||
ready = false;
|
||||
if (mc.player != null) {
|
||||
mc.player.playSound(SoundEvents.AMETHYST_BLOCK_CHIME, 1f, 1f);
|
||||
ChatUtil.info(Component.translatable("sputnik.commands.panorama.ready").getString());
|
||||
}
|
||||
}
|
||||
|
||||
@EventListener
|
||||
private void onTick(TickEvent.Post event) {
|
||||
if (mc.player == null || dir == null) return;
|
||||
|
||||
if (timer > 0) {
|
||||
--timer;
|
||||
return;
|
||||
} else {
|
||||
timer = 10;
|
||||
}
|
||||
|
||||
if (ready) {
|
||||
assembleResourcePack();
|
||||
}
|
||||
if (i < 0) return;
|
||||
|
||||
switch (i) {
|
||||
case 0 -> {
|
||||
if (!warming) {
|
||||
mc.gameRenderer.mainCamera().enablePanoramicMode();
|
||||
mc.gameRenderer.setRenderBlockOutline(false);
|
||||
mc.execute(() -> {
|
||||
synchronized (mc.levelRenderer) {
|
||||
mc.levelRenderer.notifyAll();
|
||||
}
|
||||
});
|
||||
if (!mc.gui.hud.isHidden()) mc.gui.hud.toggle();
|
||||
mc.player.setYRot(prevYaw);
|
||||
mc.player.setXRot(0f);
|
||||
warming = true;
|
||||
} else takeScreenshot();
|
||||
}
|
||||
case 1 -> {
|
||||
if (!warming) {
|
||||
mc.player.setYRot((prevYaw + 90f) % 360f);
|
||||
mc.player.setXRot(0f);
|
||||
warming = true;
|
||||
} else takeScreenshot();
|
||||
}
|
||||
case 2 -> {
|
||||
if (!warming) {
|
||||
mc.player.setYRot((prevYaw + 180f) % 360f);
|
||||
mc.player.setXRot(0f);
|
||||
warming = true;
|
||||
} else takeScreenshot();
|
||||
}
|
||||
case 3 -> {
|
||||
if (!warming) {
|
||||
mc.player.setYRot((prevYaw - 90f) % 360f);
|
||||
mc.player.setXRot(0f);
|
||||
warming = true;
|
||||
} else takeScreenshot();
|
||||
}
|
||||
case 4 -> {
|
||||
if (!warming) {
|
||||
mc.player.setYRot(prevYaw);
|
||||
mc.player.setXRot(-90f);
|
||||
warming = true;
|
||||
} else takeScreenshot();
|
||||
}
|
||||
default -> {
|
||||
if (!warming) {
|
||||
mc.player.setYRot(prevYaw);
|
||||
mc.player.setXRot(90f);
|
||||
warming = true;
|
||||
} else {
|
||||
takeScreenshot();
|
||||
i = -1;
|
||||
mc.player.setYRot(prevYaw);
|
||||
mc.player.setXRot(prevPitch);
|
||||
mc.gameRenderer.mainCamera().disablePanoramicMode();
|
||||
mc.gameRenderer.setRenderBlockOutline(true);
|
||||
mc.getWindow().setWidth(prevWidth);
|
||||
mc.getWindow().setHeight(prevHeight);
|
||||
if (mc.gui.hud.isHidden() != prevHudHidden) mc.gui.hud.toggle();
|
||||
mc.gameRenderer.mainRenderTarget().resize(prevWidth, prevHeight);
|
||||
mc.execute(() -> {
|
||||
synchronized (mc.levelRenderer) {
|
||||
mc.levelRenderer.notifyAll();
|
||||
}
|
||||
});
|
||||
|
||||
timer = 100; // esperar a que las capturas se escriban
|
||||
ready = true;
|
||||
ChatUtil.info(Component.translatable("sputnik.commands.panorama.finalizing").getString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(LiteralArgumentBuilder<SharedSuggestionProvider> builder) {
|
||||
builder.then(
|
||||
argument("name", StringArgumentType.word()).executes(ctx -> {
|
||||
String name = ctx.getArgument("name", String.class);
|
||||
begin(name);
|
||||
return SUCCESS;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public static int getPackVersion() {
|
||||
WorldVersion version = SharedConstants.getCurrentVersion();
|
||||
PackFormat format = version.packVersion(PackType.CLIENT_RESOURCES);
|
||||
return format.major();
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import me.retucio.sputnik.module.ModuleManager;
|
||||
import me.retucio.sputnik.module.modules.misc.ScreenshotPlus;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.Screenshot;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -19,14 +20,14 @@ import java.util.function.Consumer;
|
||||
@Mixin(Screenshot.class)
|
||||
public abstract class ScreenshotMixin {
|
||||
|
||||
@Inject(method = "lambda$grab$1", at = @At(value = "INVOKE", target = "Ljava/util/function/Consumer;accept(Ljava/lang/Object;)V"), cancellable = true)
|
||||
private static void sendActionsMessage(NativeImage image, File file, Consumer<?> callback, CallbackInfo ci) {
|
||||
@Inject(method = "lambda$grab$3", at = @At(value = "INVOKE", target = "Ljava/util/function/Consumer;accept(Ljava/lang/Object;)V"), cancellable = true)
|
||||
private static void sendActionsMessage(NativeImage image, File file, Consumer<Component> callback, CallbackInfo ci) {
|
||||
ScreenshotPlus screenshotPlus = getScreenshotPlus();
|
||||
if (screenshotPlus.isEnabled()) ci.cancel();
|
||||
}
|
||||
|
||||
@Inject(method = "lambda$grab$1", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/NativeImage;writeToFile(Ljava/io/File;)V"), cancellable = true)
|
||||
private static void interceptScreenshotFile(NativeImage image, File file, Consumer<?> callback, CallbackInfo ci) throws IOException {
|
||||
@Inject(method = "lambda$grab$3", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/NativeImage;writeToFile(Ljava/io/File;)V"), cancellable = true)
|
||||
private static void interceptScreenshotFile(NativeImage image, File file, Consumer<Component> callback, CallbackInfo ci) throws IOException {
|
||||
ScreenshotPlus screenshotPlus = getScreenshotPlus();
|
||||
|
||||
// aunque el módulo esté apagado, pasar las referencias para poder usar los comandos para las capturas
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package me.retucio.sputnik.util;
|
||||
|
||||
import com.github.retucio.neutrino.EventListener;
|
||||
import me.retucio.sputnik.Sputnik;
|
||||
import me.retucio.sputnik.event.TickEvent;
|
||||
import me.retucio.sputnik.module.ModuleManager;
|
||||
import me.retucio.sputnik.module.modules.client.Hud;
|
||||
@@ -8,10 +9,12 @@ import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.server.IntegratedServer;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import java.io.*;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneOffset;
|
||||
@@ -110,6 +113,26 @@ public class MiscUtil {
|
||||
}
|
||||
|
||||
|
||||
public static void copy(File from, File to) {
|
||||
try (InputStream in = new FileInputStream(from);
|
||||
OutputStream out = new FileOutputStream(to)) {
|
||||
in.transferTo(out);
|
||||
} catch (IOException e) {
|
||||
Sputnik.LOGGER.error("error copying from file \"{}\" to file \"{}\".", from.getName(), to.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void copy(InputStream in, File to) {
|
||||
try (OutputStream out = new FileOutputStream(to)) {
|
||||
in.transferTo(out);
|
||||
} catch (IOException e) {
|
||||
Sputnik.LOGGER.error("error writing to file \"{}\".", to.getName(), e);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(in);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Vec3 vec3dOf(Vector3f v) {
|
||||
return new Vec3(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
@@ -29,8 +29,13 @@
|
||||
"sputnik.commands.friend.removed": "%s is not your friend anymore :(",
|
||||
"sputnik.commands.gc.collected": "garbage collected",
|
||||
"sputnik.commands.gc.desc": "frees up ram using the garbage collector (gc)",
|
||||
"sputnik.commands.panorama.desc": "creates a panorama resource pack based on your current position",
|
||||
"sputnik.commands.panorama.errorassemble": "failed to assemble custom resource pack! does a pack of that name already exist?",
|
||||
"sputnik.commands.panorama.packdesc": "generated by Sputnik",
|
||||
"sputnik.commands.panorama.ready": "resource pack ready!",
|
||||
"sputnik.commands.panorama.finalizing": "finalizing resource pack...",
|
||||
"sputnik.commands.peek.desc": "peeks at another player's inventory",
|
||||
"sputnik.commands.plugins.calmdown": "calm dooown",
|
||||
"sputnik.commands.plugins.calmdown": "calm dooowwnnn",
|
||||
"sputnik.commands.plugins.desc": "looks for the plugins the server has",
|
||||
"sputnik.commands.plugins.erroranalyzingcommands": "error analyzing commands: %s",
|
||||
"sputnik.commands.plugins.namespacesfound": "%s command namespace(s) found:",
|
||||
|
||||
@@ -29,6 +29,11 @@
|
||||
"sputnik.commands.friend.removed": "%s ya no es tu amigo :(",
|
||||
"sputnik.commands.gc.collected": "basura recolectada",
|
||||
"sputnik.commands.gc.desc": "limpia la ram mediante el recolector de basura (gc)",
|
||||
"sputnik.commands.panorama.desc": "crea un pack de textures con la panorámica basada en tu posición actual",
|
||||
"sputnik.commands.panorama.errorassemble": "no se pudo crear el pack; existe uno ya con ese nombre?",
|
||||
"sputnik.commands.panorama.packdesc": "generado por Sputnik",
|
||||
"sputnik.commands.panorama.ready": "pack listo!",
|
||||
"sputnik.commands.panorama.finalizing": "finalizando pack...",
|
||||
"sputnik.commands.peek.desc": "cotillea el inventario de otro jugador",
|
||||
"sputnik.commands.plugins.calmdown": "calmaaa",
|
||||
"sputnik.commands.plugins.desc": "busca los plugins que tenga el server",
|
||||
|
||||
Reference in new issue
Block a user