diff --git a/src/main/java/meteordevelopment/meteorclient/commands/commands/SaveMapCommand.java b/src/main/java/meteordevelopment/meteorclient/commands/commands/SaveMapCommand.java index 573cd90d23..ee9bbcabcf 100644 --- a/src/main/java/meteordevelopment/meteorclient/commands/commands/SaveMapCommand.java +++ b/src/main/java/meteordevelopment/meteorclient/commands/commands/SaveMapCommand.java @@ -7,7 +7,9 @@ import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import meteordevelopment.meteorclient.MeteorClient; import meteordevelopment.meteorclient.commands.Command; import meteordevelopment.meteorclient.mixin.MapRendererAccessor; import net.minecraft.client.render.MapRenderer; @@ -18,7 +20,6 @@ import net.minecraft.item.Items; import net.minecraft.item.map.MapState; import net.minecraft.text.Text; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.lwjgl.BufferUtils; import org.lwjgl.PointerBuffer; @@ -26,7 +27,6 @@ import org.lwjgl.util.tinyfd.TinyFileDialogs; import javax.imageio.ImageIO; -import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; @@ -52,55 +52,43 @@ public SaveMapCommand() { @Override public void build(LiteralArgumentBuilder builder) { builder.executes(context -> { - - MapState state = getMapState(); - if (state == null) throw MAP_NOT_FOUND.create(); - ItemStack map = getMap(); - - String path = getPath(); - if (path == null) throw OOPS.create(); - - saveMap(map, state, path, 128); + saveMap(128); return SINGLE_SUCCESS; }).then(argument("scale", IntegerArgumentType.integer(1)).executes(context -> { - int scale = IntegerArgumentType.getInteger(context, "scale"); - - MapState state = getMapState(); - if (state == null) throw MAP_NOT_FOUND.create(); - ItemStack map = getMap(); - - String path = getPath(); - if (path == null) throw OOPS.create(); - - saveMap(map, state, path, scale); + saveMap(IntegerArgumentType.getInteger(context, "scale")); return SINGLE_SUCCESS; })); } - private void saveMap(@NotNull ItemStack map, MapState state, String path, int scale) { - //this is horrible code but it somehow works + private void saveMap(int scale) throws CommandSyntaxException { + ItemStack map = getMap(); + MapState state = getMapState(); + if (map == null || state == null) throw MAP_NOT_FOUND.create(); + + File path = getPath(); + if (path == null) throw OOPS.create(); MapRenderer mapRenderer = mc.gameRenderer.getMapRenderer(); MapRenderer.MapTexture texture = ((MapRendererAccessor) mapRenderer).invokeGetMapTexture(map.get(DataComponentTypes.MAP_ID), state); + if (texture.texture.getImage() == null) throw OOPS.create(); - int[] data = texture.texture.getImage().makePixelArray(); - BufferedImage image = new BufferedImage(128, 128, 2); - image.setRGB(0, 0, image.getWidth(), image.getHeight(), data, 0, 128); + try { + if (scale == 128) texture.texture.getImage().writeTo(path); + else { + int[] data = texture.texture.getImage().makePixelArray(); + BufferedImage image = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB); + image.setRGB(0, 0, image.getWidth(), image.getHeight(), data, 0, 128); - BufferedImage scaledImage = new BufferedImage(scale, scale, 2); - if (scale != 128) { - Graphics2D g = scaledImage.createGraphics(); - g.setComposite(AlphaComposite.Src); - g.drawImage(image, 0, 0, scale, scale, null); - g.dispose(); - } + BufferedImage scaledImage = new BufferedImage(scale, scale, 2); + scaledImage.createGraphics().drawImage(image, 0, 0, scale, scale, null); - try { - ImageIO.write((scale == 128 ? image : scaledImage), "png", new File(path)); + ImageIO.write(scaledImage, "png", path); + } } catch (IOException e) { - e.printStackTrace(); + error("Error writing map texture"); + MeteorClient.LOG.error(e.toString()); } } @@ -111,12 +99,12 @@ private void saveMap(@NotNull ItemStack map, MapState state, String path, int sc return FilledMapItem.getMapState(map.get(DataComponentTypes.MAP_ID), mc.world); } - private @Nullable String getPath() { + private @Nullable File getPath() { String path = TinyFileDialogs.tinyfd_saveFileDialog("Save image", null, filters, null); if (path == null) return null; if (!path.endsWith(".png")) path += ".png"; - return path; + return new File(path); } private @Nullable ItemStack getMap() { diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/MinecraftClientMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/MinecraftClientMixin.java index c07acd01bc..68edcb4a23 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/MinecraftClientMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/MinecraftClientMixin.java @@ -19,6 +19,7 @@ import meteordevelopment.meteorclient.systems.config.Config; import meteordevelopment.meteorclient.systems.modules.Modules; import meteordevelopment.meteorclient.systems.modules.player.FastUse; +import meteordevelopment.meteorclient.systems.modules.player.Multitask; import meteordevelopment.meteorclient.systems.modules.render.UnfocusedCPU; import meteordevelopment.meteorclient.utils.Utils; import meteordevelopment.meteorclient.utils.misc.CPSUtils; @@ -28,6 +29,7 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.Mouse; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerInteractionManager; import net.minecraft.client.option.GameOptions; import net.minecraft.client.util.Window; @@ -74,6 +76,10 @@ public abstract class MinecraftClientMixin implements IMinecraftClient { @Shadow private int itemUseCooldown; + @Shadow + @Nullable + public ClientPlayerEntity player; + @Inject(method = "", at = @At("TAIL")) private void onInit(CallbackInfo info) { MeteorClient.INSTANCE.onInitializeClient(); @@ -186,10 +192,35 @@ private void onRender(CallbackInfo info) { lastTime = time; } + // multitask + + @ModifyExpressionValue(method = "doItemUse", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;isBreakingBlock()Z")) + private boolean doItemUseModifyIsBreakingBlock(boolean original) { + return !Modules.get().isActive(Multitask.class) && original; + } + + @ModifyExpressionValue(method = "handleBlockBreaking", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isUsingItem()Z")) + private boolean handleBlockBreakingModifyIsUsingItem(boolean original) { + return !Modules.get().isActive(Multitask.class) && original; + } + + @ModifyExpressionValue(method = "handleInputEvents", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isUsingItem()Z", ordinal = 0)) + private boolean handleInputEventsModifyIsUsingItem(boolean original) { + return !Modules.get().get(Multitask.class).attackingEntities() && original; + } + + @Inject(method = "handleInputEvents", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isUsingItem()Z", ordinal = 0, shift = At.Shift.BEFORE)) + private void handleInputEventsInjectStopUsingItem(CallbackInfo info) { + if (Modules.get().get(Multitask.class).attackingEntities() && player.isUsingItem()) { + if (!options.useKey.isPressed()) interactionManager.stopUsingItem(player); + while (options.useKey.wasPressed()); + } + } + // Interface @Override - public void rightClick() { + public void meteor_client$rightClick() { rightClick = true; } } diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/ScreenMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/ScreenMixin.java index 41b7676137..5aebc5034a 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixin/ScreenMixin.java +++ b/src/main/java/meteordevelopment/meteorclient/mixin/ScreenMixin.java @@ -6,6 +6,7 @@ package meteordevelopment.meteorclient.mixin; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import meteordevelopment.meteorclient.MeteorClient; import meteordevelopment.meteorclient.commands.Commands; import meteordevelopment.meteorclient.systems.config.Config; import meteordevelopment.meteorclient.systems.modules.Modules; @@ -30,8 +31,8 @@ @Mixin(value = Screen.class, priority = 500) // needs to be before baritone public abstract class ScreenMixin { - @Inject(method = "renderBackground", at = @At("HEAD"), cancellable = true) - private void onRenderBackground(CallbackInfo info) { + @Inject(method = "renderInGameBackground", at = @At("HEAD"), cancellable = true) + private void onRenderInGameBackground(CallbackInfo info) { if (Utils.canUpdate() && Modules.get().get(NoRender.class).noGuiBackground()) info.cancel(); } @@ -51,7 +52,7 @@ private void onRunCommand(Style style, CallbackInfoReturnable cir) { Commands.dispatch(style.getClickEvent().getValue().substring(Config.get().prefix.get().length())); cir.setReturnValue(true); } catch (CommandSyntaxException e) { - e.printStackTrace(); + MeteorClient.LOG.error("Failed to run command", e); } } } diff --git a/src/main/java/meteordevelopment/meteorclient/mixin/ServerResourcePackLoaderMixin.java b/src/main/java/meteordevelopment/meteorclient/mixin/ServerResourcePackLoaderMixin.java new file mode 100644 index 0000000000..1ab4890f01 --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/mixin/ServerResourcePackLoaderMixin.java @@ -0,0 +1,22 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package meteordevelopment.meteorclient.mixin; + +import meteordevelopment.meteorclient.systems.modules.Modules; +import meteordevelopment.meteorclient.systems.modules.misc.ServerSpoof; +import net.minecraft.client.resource.server.ServerResourcePackLoader; +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.CallbackInfo; + +@Mixin(ServerResourcePackLoader.class) +public class ServerResourcePackLoaderMixin { + @Inject(method = "onReloadSuccess", at = @At("TAIL")) + private void removeInactivePacksTail(CallbackInfo ci) { + Modules.get().get(ServerSpoof.class).silentAcceptResourcePack = false; + } +} diff --git a/src/main/java/meteordevelopment/meteorclient/mixininterface/IMinecraftClient.java b/src/main/java/meteordevelopment/meteorclient/mixininterface/IMinecraftClient.java index 0438a29b83..4e74162574 100644 --- a/src/main/java/meteordevelopment/meteorclient/mixininterface/IMinecraftClient.java +++ b/src/main/java/meteordevelopment/meteorclient/mixininterface/IMinecraftClient.java @@ -6,5 +6,5 @@ package meteordevelopment.meteorclient.mixininterface; public interface IMinecraftClient { - void rightClick(); + void meteor_client$rightClick(); } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java index 5b0b98343a..88f47fc812 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/Modules.java @@ -430,11 +430,13 @@ private void initCombat() { private void initPlayer() { add(new AntiHunger()); add(new AutoEat()); + add(new AutoClicker()); add(new AutoFish()); add(new AutoGap()); add(new AutoMend()); add(new AutoReplenish()); add(new AutoTool()); + add(new BreakDelay()); add(new ChestSwap()); add(new EXPThrower()); add(new FakePlayer()); @@ -443,12 +445,11 @@ private void initPlayer() { add(new InstantRebreak()); add(new LiquidInteract()); add(new MiddleClickExtra()); - add(new BreakDelay()); + add(new Multitask()); add(new NoInteract()); add(new NoMiningTrace()); add(new NoRotate()); add(new OffhandCrash()); - add(new PacketMine()); add(new Portals()); add(new PotionSaver()); add(new PotionSpoof()); @@ -538,7 +539,6 @@ private void initRender() { private void initWorld() { add(new AirPlace()); add(new Ambience()); - add(new Collisions()); add(new AutoBreed()); add(new AutoBrewer()); add(new AutoMount()); @@ -547,18 +547,20 @@ private void initWorld() { add(new AutoSign()); add(new AutoSmelter()); add(new BuildHeight()); + add(new Collisions()); add(new EChestFarmer()); add(new EndermanLook()); add(new Flamethrower()); + add(new HighwayBuilder()); add(new LiquidFiller()); add(new MountBypass()); add(new NoGhostBlocks()); add(new Nuker()); + add(new PacketMine()); add(new StashFinder()); add(new SpawnProofer()); add(new Timer()); add(new VeinMiner()); - add(new HighwayBuilder()); if (BaritoneUtils.IS_AVAILABLE) { add(new Excavator()); @@ -569,7 +571,6 @@ private void initWorld() { private void initMisc() { add(new Swarm()); add(new AntiPacketKick()); - add(new AutoClicker()); add(new AutoLog()); add(new AutoReconnect()); add(new AutoRespawn()); @@ -577,15 +578,15 @@ private void initMisc() { add(new BetterChat()); add(new BookBot()); add(new DiscordPresence()); + add(new InventoryTweaks()); add(new MessageAura()); add(new NameProtect()); add(new Notebot()); add(new Notifier()); add(new PacketCanceller()); + add(new ServerSpoof()); add(new SoundBlocker()); add(new Spam()); - add(new ServerSpoof()); - add(new InventoryTweaks()); } public static class ModuleRegistry extends SimpleRegistry { diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/ServerSpoof.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/ServerSpoof.java index a81d9bd882..d312a2c425 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/ServerSpoof.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/misc/ServerSpoof.java @@ -6,9 +6,11 @@ package meteordevelopment.meteorclient.systems.modules.misc; import meteordevelopment.meteorclient.events.packets.PacketEvent; +import meteordevelopment.meteorclient.events.world.TickEvent; import meteordevelopment.meteorclient.settings.*; import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Module; +import meteordevelopment.meteorclient.utils.Utils; import meteordevelopment.meteorclient.utils.misc.text.RunnableClickEvent; import meteordevelopment.orbit.EventHandler; import net.minecraft.network.packet.BrandCustomPayload; @@ -23,6 +25,10 @@ import net.minecraft.util.Identifier; import org.apache.commons.lang3.StringUtils; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; import java.util.List; public class ServerSpoof extends Module { @@ -65,6 +71,9 @@ public class ServerSpoof extends Module { .build() ); + private MutableText msg; + public boolean silentAcceptResourcePack = false; + public ServerSpoof() { super(Categories.Misc, "server-spoof", "Spoof client brand, resource pack and channels."); @@ -73,60 +82,88 @@ public ServerSpoof() { @EventHandler private void onPacketSend(PacketEvent.Send event) { - if (!isActive() || !(event.packet instanceof CustomPayloadC2SPacket)) return; - Identifier id = ((CustomPayloadC2SPacket) event.packet).payload().getId().id(); - - if (blockChannels.get()) { - for (String channel : channels.get()) { - if (StringUtils.containsIgnoreCase(id.toString(), channel)) { - event.cancel(); - return; + if (!isActive()) return; + + if (event.packet instanceof CustomPayloadC2SPacket) { + Identifier id = ((CustomPayloadC2SPacket) event.packet).payload().getId().id(); + + if (blockChannels.get()) { + for (String channel : channels.get()) { + if (StringUtils.containsIgnoreCase(id.toString(), channel)) { + event.cancel(); + return; + } } } - } - if (spoofBrand.get() && id.equals(BrandCustomPayload.ID.id())) { - CustomPayloadC2SPacket spoofedPacket = new CustomPayloadC2SPacket(new BrandCustomPayload(brand.get())); + if (spoofBrand.get() && id.equals(BrandCustomPayload.ID.id())) { + CustomPayloadC2SPacket spoofedPacket = new CustomPayloadC2SPacket(new BrandCustomPayload(brand.get())); - // PacketEvent.Send doesn't trigger if we send the packet like this - event.connection.send(spoofedPacket, null, true); - event.cancel(); + // PacketEvent.Send doesn't trigger if we send the packet like this + event.connection.send(spoofedPacket, null, true); + event.cancel(); + } } + + // we want to accept the pack silently to prevent the server detecting you bypassed it when logging in + if (silentAcceptResourcePack && event.packet instanceof ResourcePackStatusC2SPacket) event.cancel(); } @EventHandler private void onPacketReceive(PacketEvent.Receive event) { - if (!isActive()) return; + if (!isActive() || !resourcePack.get()) return; + if (!(event.packet instanceof ResourcePackSendS2CPacket packet)) return; + + event.cancel(); + event.connection.send(new ResourcePackStatusC2SPacket(packet.id(), ResourcePackStatusC2SPacket.Status.ACCEPTED)); + event.connection.send(new ResourcePackStatusC2SPacket(packet.id(), ResourcePackStatusC2SPacket.Status.DOWNLOADED)); + event.connection.send(new ResourcePackStatusC2SPacket(packet.id(), ResourcePackStatusC2SPacket.Status.SUCCESSFULLY_LOADED)); + + msg = Text.literal("This server has "); + msg.append(packet.required() ? "a required " : "an optional ").append("resource pack. "); + + MutableText link = Text.literal("[Open URL]"); + link.setStyle(link.getStyle() + .withColor(Formatting.BLUE) + .withUnderline(true) + .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, packet.url())) + .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.literal("Click to open the pack url"))) + ); + + MutableText acceptance = Text.literal("[Accept Pack]"); + acceptance.setStyle(acceptance.getStyle() + .withColor(Formatting.DARK_GREEN) + .withUnderline(true) + .withClickEvent(new RunnableClickEvent(() -> { + URL url = getParsedResourcePackUrl(packet.url()); + if (url == null) error("Invalid resource pack URL: " + packet.url()); + else { + silentAcceptResourcePack = true; + mc.getServerResourcePackProvider().addResourcePack(packet.id(), url, packet.hash()); + } + })) + .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.literal("Click to accept and apply the pack."))) + ); + + msg.append(link).append(" "); + msg.append(acceptance).append("."); + } + + @EventHandler + private void onTick(TickEvent.Pre event) { + if (!isActive() || !Utils.canUpdate() || msg == null) return; + + info(msg); + msg = null; + } - if (resourcePack.get()) { - if (!(event.packet instanceof ResourcePackSendS2CPacket packet)) return; - event.cancel(); - - MutableText msg = Text.literal("This server has "); - msg.append(packet.required() ? "a required " : "an optional ").append("resource pack. "); - - MutableText link = Text.literal("[Download]"); - link.setStyle(link.getStyle() - .withColor(Formatting.BLUE) - .withUnderline(true) - .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, packet.url())) - .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.literal("Click to download"))) - ); - - MutableText acceptance = Text.literal("[Spoof Acceptance]"); - acceptance.setStyle(acceptance.getStyle() - .withColor(Formatting.DARK_GREEN) - .withUnderline(true) - .withClickEvent(new RunnableClickEvent(() -> { - event.connection.send(new ResourcePackStatusC2SPacket(packet.id(), ResourcePackStatusC2SPacket.Status.ACCEPTED)); - event.connection.send(new ResourcePackStatusC2SPacket(packet.id(), ResourcePackStatusC2SPacket.Status.SUCCESSFULLY_LOADED)); - })) - .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.literal("Click to spoof accepting the recourse pack."))) - ); - - msg.append(link).append(" "); - msg.append(acceptance).append("."); - info(msg); + private static URL getParsedResourcePackUrl(String url) { + try { + URL uRL = new URI(url).toURL(); + String string = uRL.getProtocol(); + return !"http".equals(string) && !"https".equals(string) ? null : uRL; + } catch (MalformedURLException | URISyntaxException var3) { + return null; } } } diff --git a/src/main/java/meteordevelopment/meteorclient/systems/modules/player/Multitask.java b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/Multitask.java new file mode 100644 index 0000000000..62a5b98abe --- /dev/null +++ b/src/main/java/meteordevelopment/meteorclient/systems/modules/player/Multitask.java @@ -0,0 +1,31 @@ +/* + * This file is part of the Meteor Client distribution (https://github.com/MeteorDevelopment/meteor-client). + * Copyright (c) Meteor Development. + */ + +package meteordevelopment.meteorclient.systems.modules.player; + +import meteordevelopment.meteorclient.settings.BoolSetting; +import meteordevelopment.meteorclient.settings.Setting; +import meteordevelopment.meteorclient.settings.SettingGroup; +import meteordevelopment.meteorclient.systems.modules.Categories; +import meteordevelopment.meteorclient.systems.modules.Module; + +public class Multitask extends Module { + private final SettingGroup sgGeneral = settings.getDefaultGroup(); + + private final Setting attackingEntities = sgGeneral.add(new BoolSetting.Builder() + .name("attacking-entities") + .description("Lets you attack entities while using an item.") + .defaultValue(true) + .build() + ); + + public Multitask() { + super(Categories.Player, "multitask", "Lets you use items and attack at the same time."); + } + + public boolean attackingEntities() { + return isActive() && attackingEntities.get(); + } +} diff --git a/src/main/java/meteordevelopment/meteorclient/systems/waypoints/Waypoints.java b/src/main/java/meteordevelopment/meteorclient/systems/waypoints/Waypoints.java index 193dae163d..022678839d 100644 --- a/src/main/java/meteordevelopment/meteorclient/systems/waypoints/Waypoints.java +++ b/src/main/java/meteordevelopment/meteorclient/systems/waypoints/Waypoints.java @@ -187,7 +187,7 @@ public Waypoint next() { @Override public void remove() { - Iterator.super.remove(); + it.remove(); save(); } } diff --git a/src/main/java/meteordevelopment/meteorclient/utils/Utils.java b/src/main/java/meteordevelopment/meteorclient/utils/Utils.java index 547948bba9..a0d2b70d67 100644 --- a/src/main/java/meteordevelopment/meteorclient/utils/Utils.java +++ b/src/main/java/meteordevelopment/meteorclient/utils/Utils.java @@ -519,7 +519,7 @@ public static void leftClick() { } public static void rightClick() { - ((IMinecraftClient) mc).rightClick(); + ((IMinecraftClient) mc).meteor_client$rightClick(); } public static boolean isShulker(Item item) { diff --git a/src/main/resources/meteor-client.mixins.json b/src/main/resources/meteor-client.mixins.json index 02345053b9..414a0b9a23 100644 --- a/src/main/resources/meteor-client.mixins.json +++ b/src/main/resources/meteor-client.mixins.json @@ -154,6 +154,7 @@ "ResourceReloadLoggerAccessor", "ScreenMixin", "SectionedEntityCacheAccessor", + "ServerResourcePackLoaderMixin", "ShapeIndexBufferAccessor", "ShulkerBoxBlockMixin", "SignBlockEntityRendererMixin",