1
mirror of https://github.com/Shiewk/ViewServerResources.git synced 2026-04-28 03:44:17 +02:00

Allow viewing resource pack URLs

This commit is contained in:
Shy
2024-08-24 13:01:23 +02:00
parent f45a0d847d
commit deefdf90c3
8 changed files with 228 additions and 1 deletions
@@ -1,10 +1,18 @@
package de.shiewk.resourcepackprivacy.client; package de.shiewk.resourcepackprivacy.client;
import de.shiewk.resourcepackprivacy.event.ChatAnnouncer;
import de.shiewk.resourcepackprivacy.event.ScreenListener;
import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientEntityEvents;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
public class ResourcePackPrivacyClient implements ClientModInitializer { public class ResourcePackPrivacyClient implements ClientModInitializer {
@Override @Override
public void onInitializeClient() { public void onInitializeClient() {
ScreenEvents.AFTER_INIT.register(new ScreenListener());
} }
} }
@@ -0,0 +1,79 @@
package de.shiewk.resourcepackprivacy.event;
import de.shiewk.resourcepackprivacy.ResourcePackPrivacy;
import de.shiewk.resourcepackprivacy.mixin.AccessorConfirmServerResourcePackScreen;
import de.shiewk.resourcepackprivacy.mixin.AccessorConfirmServerResourcePackScreenPack;
import de.shiewk.resourcepackprivacy.mixin.MixinClientCommonNetworkHandler;
import de.shiewk.resourcepackprivacy.screen.ViewResourceURLsScreen;
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
import net.fabricmc.fabric.api.client.screen.v1.Screens;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ConfirmScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.*;
import net.minecraft.client.network.ClientCommonNetworkHandler;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class ScreenListener implements ScreenEvents.AfterInit {
private static final int buttonWidth = 150;
public record PackInfo(UUID id, URL url, String hash){}
@Override
public void afterInit(MinecraftClient client, Screen screen, int scaledWidth, int scaledHeight) {
if (screen instanceof ConfirmScreen && screen.getClass().getEnclosingClass() == ClientCommonNetworkHandler.class){
GridWidget gw = new GridWidget();
gw.getMainPositioner().margin(4, 4, 4, 0);
final GridWidget.Adder adder = gw.createAdder(2);
final List<ClickableWidget> buttons = Screens.getButtons(screen);
final List<PackInfo> infos = getPackInfos((AccessorConfirmServerResourcePackScreen) screen);
while (!buttons.isEmpty()){
adder.add(buttons.removeFirst());
}
adder.add(createButton(Text.translatable(infos.size() == 1 ? "gui.resourcepackprivacy.viewURL" : "gui.resourcepackprivacy.viewURLs"), btn -> viewURLs(client, screen, infos)));
adder.add(createButton(Text.translatable(infos.size() == 1 ? "gui.resourcepackprivacy.alwaysURL" : "gui.resourcepackprivacy.alwaysURLs"), btn -> btn.active = false));
adder.add(createLargeButton(Text.translatable("gui.resourcepackprivacy.alwaysHost", Text.literal(infos.getFirst().url().getHost()).withColor(Color.GREEN.getRGB())), btn -> btn.active = false), 2);
gw.refreshPositions();
SimplePositioningWidget.setPos(gw, 0, 0, scaledWidth, scaledHeight, 0.5F, 0.875F);
gw.forEachChild(buttons::add);
}
}
private void viewURLs(MinecraftClient client, Screen screen, List<PackInfo> infos) {
client.setScreen(new ViewResourceURLsScreen(screen, infos));
}
private static @NotNull List<PackInfo> getPackInfos(AccessorConfirmServerResourcePackScreen screen) {
final List<PackInfo> infos = new ArrayList<>();
final List<?> packs = screen.getPacks();
for (Object packObj : packs) {
AccessorConfirmServerResourcePackScreenPack pack = (AccessorConfirmServerResourcePackScreenPack) packObj;
infos.add(new PackInfo(pack.getId(), pack.getURL(), pack.getHash()));
}
return infos;
}
private ButtonWidget createButton(Text m, ButtonWidget.PressAction action){
return ButtonWidget.builder(m, action).width(buttonWidth).build();
}
private ButtonWidget createLargeButton(Text m, ButtonWidget.PressAction action){
return ButtonWidget.builder(m, action).width(buttonWidth*2+8).build();
}
}
@@ -0,0 +1,16 @@
package de.shiewk.resourcepackprivacy.mixin;
import net.minecraft.client.network.ClientCommonNetworkHandler;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
@Mixin(targets = "net/minecraft/client/network/ClientCommonNetworkHandler/ConfirmServerResourcePackScreen")
public interface AccessorConfirmServerResourcePackScreen {
@Accessor(value = "packs")
List<?> getPacks();
// ? type because the class is private
}
@@ -0,0 +1,22 @@
package de.shiewk.resourcepackprivacy.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.net.URL;
import java.util.UUID;
@Mixin(targets = "net/minecraft/client/network/ClientCommonNetworkHandler/ConfirmServerResourcePackScreen/Pack")
public interface AccessorConfirmServerResourcePackScreenPack {
@Accessor(value = "id")
UUID getId();
@Accessor(value = "url")
URL getURL();
@Accessor(value = "hash")
String getHash();
}
@@ -0,0 +1,40 @@
package de.shiewk.resourcepackprivacy.mixin;
import com.llamalad7.mixinextras.sugar.Local;
import de.shiewk.resourcepackprivacy.ResourcePackPrivacy;
import net.fabricmc.fabric.mixin.networking.client.accessor.ClientCommonNetworkHandlerAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.ClientCommonNetworkHandler;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.packet.s2c.common.ResourcePackSendS2CPacket;
import net.minecraft.text.Text;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
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.CallbackInfo;
import java.awt.*;
import java.net.URL;
import java.util.UUID;
@Mixin(ClientCommonNetworkHandler.class)
public abstract class MixinClientCommonNetworkHandler {
@Shadow protected abstract Screen createConfirmServerResourcePackScreen(UUID id, URL url, String hash, boolean required, @Nullable Text prompt);
@Shadow @Final protected MinecraftClient client;
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/network/packet/s2c/common/ResourcePackSendS2CPacket;hash()Ljava/lang/String;"), method = "onResourcePackSend", cancellable = true)
public void onResourcePackSend(ResourcePackSendS2CPacket packet, CallbackInfo ci, @Local UUID uUID, @Local URL uRL){
ResourcePackPrivacy.LOGGER.info(packet.url());
String hash = packet.hash();
boolean required = packet.required();
this.client.setScreen(this.createConfirmServerResourcePackScreen(uUID, uRL, hash, required, packet.prompt().orElse(null)));
ci.cancel();
}
}
@@ -0,0 +1,48 @@
package de.shiewk.resourcepackprivacy.screen;
import de.shiewk.resourcepackprivacy.event.ScreenListener;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.MultilineTextWidget;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import java.awt.*;
import java.util.List;
public class ViewResourceURLsScreen extends Screen {
private final Screen parent;
private final List<ScreenListener.PackInfo> infos;
public ViewResourceURLsScreen(Screen parent, List<ScreenListener.PackInfo> infos) {
super(Text.translatable("gui.resourcepackprivacy.viewURL"));
this.parent = parent;
this.infos = infos;
}
@Override
public void close() {
assert client != null;
client.setScreen(parent);
}
@Override
protected void init() {
addDrawableChild(ButtonWidget.builder(Text.translatable("gui.done"), btn -> this.close())
.dimensions(width / 2 - 150, height - 30, 300, 20)
.build());
final MultilineTextWidget text = new MultilineTextWidget(getMessage(), textRenderer);
text.setCentered(true);
text.setPosition(width / 2 - (text.getWidth() / 2), height / 2 - (text.getHeight() / 2));
addDrawableChild(text);
}
private Text getMessage(){
MutableText msg = Text.empty();
for (ScreenListener.PackInfo info : infos) {
msg = msg.append(Text.literal("\n"+info.url()));
}
return Text.translatable(infos.size() == 1 ? "gui.resourcepackprivacy.url" : "gui.resourcepackprivacy.urls", msg).withColor(Color.GREEN.getRGB());
}
}
@@ -0,0 +1,12 @@
{
"gui.resourcepackprivacy.confirmScreen": "Confirm Server Resource Pack",
"gui.resourcepackprivacy.accept": "Accept once",
"gui.resourcepackprivacy.decline": "Decline once",
"gui.resourcepackprivacy.url": "The pack will be downloaded from: %s",
"gui.resourcepackprivacy.urls": "The packs will be downloaded from: %s",
"gui.resourcepackprivacy.alwaysURL": "Always accept this URL",
"gui.resourcepackprivacy.alwaysURLs": "Always accept these URLs",
"gui.resourcepackprivacy.alwaysHost": "Always accept packs from %s",
"gui.resourcepackprivacy.viewURL": "View download URL",
"gui.resourcepackprivacy.viewURLs": "View download URLs"
}
@@ -6,7 +6,9 @@
"mixins": [ "mixins": [
], ],
"client": [ "client": [
"AccessorConfirmServerResourcePackScreen",
"AccessorConfirmServerResourcePackScreenPack",
"MixinClientCommonNetworkHandler"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1