diff --git a/gradle.properties b/gradle.properties
index af50cc7004..a10b2a86cc 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -5,15 +5,15 @@ org.gradle.parallel=true
 # Fabric Properties
 # check these at https://fabricmc.net/develop/ and
 # https://www.curseforge.com/minecraft/mc-mods/fabric-api
-minecraft_version=1.20.2
-yarn_mappings=1.20.2+build.4
+minecraft_version=1.20.4
+yarn_mappings=1.20.4+build.3
 loader_version=0.15.2
 
 #Fabric api
-fabric_version=0.91.2+1.20.2
+fabric_version=0.91.2+1.20.4
 
 # Mod Properties
-mod_version = v7.40-MC1.20.2
+mod_version = v7.40-MC1.20.4
 maven_group = net.wurstclient
 archives_base_name = Wurst-Client
 
diff --git a/src/main/java/net/wurstclient/FriendsList.java b/src/main/java/net/wurstclient/FriendsList.java
index 3e166752bd..22261e01ee 100644
--- a/src/main/java/net/wurstclient/FriendsList.java
+++ b/src/main/java/net/wurstclient/FriendsList.java
@@ -60,7 +60,7 @@ public void middleClick(Entity entity)
 		if(!middleClickFriends.isChecked())
 			return;
 		
-		String name = entity.getEntityName();
+		String name = entity.getName().getString();
 		
 		if(contains(name))
 			removeAndSave(name);
@@ -75,7 +75,7 @@ public boolean contains(String name)
 	
 	public boolean isFriend(Entity entity)
 	{
-		return entity != null && contains(entity.getEntityName());
+		return entity != null && contains(entity.getName().getString());
 	}
 	
 	public ArrayList<String> toList()
diff --git a/src/main/java/net/wurstclient/WurstClient.java b/src/main/java/net/wurstclient/WurstClient.java
index e63b17e404..5f0025c21b 100644
--- a/src/main/java/net/wurstclient/WurstClient.java
+++ b/src/main/java/net/wurstclient/WurstClient.java
@@ -58,7 +58,7 @@ public enum WurstClient
 	public static IMinecraftClient IMC;
 	
 	public static final String VERSION = "7.40";
-	public static final String MC_VERSION = "1.20.2";
+	public static final String MC_VERSION = "1.20.4";
 	
 	private WurstAnalytics analytics;
 	private EventManager eventManager;
diff --git a/src/main/java/net/wurstclient/commands/CopyItemCmd.java b/src/main/java/net/wurstclient/commands/CopyItemCmd.java
index 5c2dea044a..08ff593503 100644
--- a/src/main/java/net/wurstclient/commands/CopyItemCmd.java
+++ b/src/main/java/net/wurstclient/commands/CopyItemCmd.java
@@ -47,7 +47,7 @@ private AbstractClientPlayerEntity getPlayer(String name) throws CmdError
 	{
 		for(AbstractClientPlayerEntity player : MC.world.getPlayers())
 		{
-			if(!player.getEntityName().equalsIgnoreCase(name))
+			if(!player.getName().getString().equalsIgnoreCase(name))
 				continue;
 			
 			return player;
diff --git a/src/main/java/net/wurstclient/hacks/AnchorAuraHack.java b/src/main/java/net/wurstclient/hacks/AnchorAuraHack.java
index 824fa6922c..554494f589 100644
--- a/src/main/java/net/wurstclient/hacks/AnchorAuraHack.java
+++ b/src/main/java/net/wurstclient/hacks/AnchorAuraHack.java
@@ -333,7 +333,8 @@ private ArrayList<Entity> getNearbyTargets()
 					&& ((LivingEntity)e).getHealth() > 0)
 				.filter(e -> e != MC.player)
 				.filter(e -> !(e instanceof FakePlayerEntity))
-				.filter(e -> !WURST.getFriends().contains(e.getEntityName()))
+				.filter(
+					e -> !WURST.getFriends().contains(e.getName().getString()))
 				.filter(e -> MC.player.squaredDistanceTo(e) <= rangeSq);
 		
 		stream = entityFilters.applyTo(stream);
diff --git a/src/main/java/net/wurstclient/hacks/AutoFarmHack.java b/src/main/java/net/wurstclient/hacks/AutoFarmHack.java
index 9406254993..0a1ef5522c 100644
--- a/src/main/java/net/wurstclient/hacks/AutoFarmHack.java
+++ b/src/main/java/net/wurstclient/hacks/AutoFarmHack.java
@@ -206,7 +206,7 @@ private boolean shouldBeHarvested(BlockPos pos)
 		if(block instanceof CocoaBlock)
 			return state.get(CocoaBlock.AGE) >= 2;
 		
-		if(block instanceof GourdBlock)
+		if(block == Blocks.PUMPKIN || block == Blocks.MELON)
 			return true;
 		
 		if(block instanceof SugarCaneBlock)
diff --git a/src/main/java/net/wurstclient/hacks/ChestEspHack.java b/src/main/java/net/wurstclient/hacks/ChestEspHack.java
index 18b23871a0..47757501c6 100644
--- a/src/main/java/net/wurstclient/hacks/ChestEspHack.java
+++ b/src/main/java/net/wurstclient/hacks/ChestEspHack.java
@@ -79,6 +79,11 @@ public class ChestEspHack extends Hack implements UpdateListener,
 			"Barrels will be highlighted in this color.", Color.GREEN),
 		new CheckboxSetting("Include barrels", true));
 	
+	private final ChestEspBlockGroup pots = new ChestEspBlockGroup(
+		new ColorSetting("Pots color",
+			"Decorated pots will be highlighted in this color.", Color.GREEN),
+		new CheckboxSetting("Include pots", false));
+	
 	private final ChestEspBlockGroup shulkerBoxes = new ChestEspBlockGroup(
 		new ColorSetting("Shulker color",
 			"Shulker boxes will be highlighted in this color.", Color.MAGENTA),
@@ -107,14 +112,20 @@ public class ChestEspHack extends Hack implements UpdateListener,
 			new Color(0xFF8000)),
 		new CheckboxSetting("Include dispensers", false));
 	
+	private final ChestEspBlockGroup crafters = new ChestEspBlockGroup(
+		new ColorSetting("Crafter color",
+			"Crafters will be highlighted in this color.", Color.WHITE),
+		new CheckboxSetting("Include crafters", false));
+	
 	private final ChestEspBlockGroup furnaces =
 		new ChestEspBlockGroup(new ColorSetting("Furnace color",
 			"Furnaces, smokers, and blast furnaces will be highlighted in this color.",
 			Color.RED), new CheckboxSetting("Include furnaces", false));
 	
-	private final List<ChestEspGroup> groups = Arrays.asList(basicChests,
-		trapChests, enderChests, chestCarts, chestBoats, barrels, shulkerBoxes,
-		hoppers, hopperCarts, droppers, dispensers, furnaces);
+	private final List<ChestEspGroup> groups =
+		Arrays.asList(basicChests, trapChests, enderChests, chestCarts,
+			chestBoats, barrels, pots, shulkerBoxes, hoppers, hopperCarts,
+			droppers, dispensers, crafters, furnaces);
 	
 	private final List<ChestEspEntityGroup> entityGroups =
 		Arrays.asList(chestCarts, chestBoats, hopperCarts);
@@ -170,12 +181,16 @@ else if(blockEntity instanceof ShulkerBoxBlockEntity)
 				shulkerBoxes.add(blockEntity);
 			else if(blockEntity instanceof BarrelBlockEntity)
 				barrels.add(blockEntity);
+			else if(blockEntity instanceof DecoratedPotBlockEntity)
+				pots.add(blockEntity);
 			else if(blockEntity instanceof HopperBlockEntity)
 				hoppers.add(blockEntity);
 			else if(blockEntity instanceof DropperBlockEntity)
 				droppers.add(blockEntity);
 			else if(blockEntity instanceof DispenserBlockEntity)
 				dispensers.add(blockEntity);
+			else if(blockEntity instanceof CrafterBlockEntity)
+				crafters.add(blockEntity);
 			else if(blockEntity instanceof AbstractFurnaceBlockEntity)
 				furnaces.add(blockEntity);
 			
diff --git a/src/main/java/net/wurstclient/hacks/CrystalAuraHack.java b/src/main/java/net/wurstclient/hacks/CrystalAuraHack.java
index 28cb935353..b19cfaae13 100644
--- a/src/main/java/net/wurstclient/hacks/CrystalAuraHack.java
+++ b/src/main/java/net/wurstclient/hacks/CrystalAuraHack.java
@@ -251,7 +251,8 @@ private ArrayList<Entity> getNearbyTargets()
 					&& ((LivingEntity)e).getHealth() > 0)
 				.filter(e -> e != MC.player)
 				.filter(e -> !(e instanceof FakePlayerEntity))
-				.filter(e -> !WURST.getFriends().contains(e.getEntityName()))
+				.filter(
+					e -> !WURST.getFriends().contains(e.getName().getString()))
 				.filter(e -> MC.player.squaredDistanceTo(e) <= rangeSq);
 		
 		stream = entityFilters.applyTo(stream);
diff --git a/src/main/java/net/wurstclient/hacks/PlayerEspHack.java b/src/main/java/net/wurstclient/hacks/PlayerEspHack.java
index a44a5d2e1c..2b2835f498 100644
--- a/src/main/java/net/wurstclient/hacks/PlayerEspHack.java
+++ b/src/main/java/net/wurstclient/hacks/PlayerEspHack.java
@@ -160,7 +160,7 @@ private void renderBoxes(MatrixStack matrixStack, float partialTicks,
 				e.getHeight() + extraSize, e.getWidth() + extraSize);
 			
 			// set color
-			if(WURST.getFriends().contains(e.getEntityName()))
+			if(WURST.getFriends().contains(e.getName().getString()))
 				RenderSystem.setShaderColor(0, 0, 1, 0.5F);
 			else
 			{
@@ -199,7 +199,7 @@ private void renderTracers(MatrixStack matrixStack, float partialTicks,
 			
 			float r, g, b;
 			
-			if(WURST.getFriends().contains(e.getEntityName()))
+			if(WURST.getFriends().contains(e.getName().getString()))
 			{
 				r = 0;
 				g = 0;
diff --git a/src/main/java/net/wurstclient/hacks/XRayHack.java b/src/main/java/net/wurstclient/hacks/XRayHack.java
index 648582ed7b..77b6160e07 100644
--- a/src/main/java/net/wurstclient/hacks/XRayHack.java
+++ b/src/main/java/net/wurstclient/hacks/XRayHack.java
@@ -47,7 +47,8 @@ public final class XRayHack extends Hack implements UpdateListener,
 		"minecraft:brewing_stand", "minecraft:chain_command_block",
 		"minecraft:chest", "minecraft:clay", "minecraft:coal_block",
 		"minecraft:coal_ore", "minecraft:command_block", "minecraft:copper_ore",
-		"minecraft:crafting_table", "minecraft:deepslate_coal_ore",
+		"minecraft:crafter", "minecraft:crafting_table",
+		"minecraft:decorated_pot", "minecraft:deepslate_coal_ore",
 		"minecraft:deepslate_copper_ore", "minecraft:deepslate_diamond_ore",
 		"minecraft:deepslate_emerald_ore", "minecraft:deepslate_gold_ore",
 		"minecraft:deepslate_iron_ore", "minecraft:deepslate_lapis_ore",
diff --git a/src/main/java/net/wurstclient/mixin/DirectConnectScreenMixin.java b/src/main/java/net/wurstclient/mixin/DirectConnectScreenMixin.java
index 31a195b8e3..c65e19cf4c 100644
--- a/src/main/java/net/wurstclient/mixin/DirectConnectScreenMixin.java
+++ b/src/main/java/net/wurstclient/mixin/DirectConnectScreenMixin.java
@@ -14,8 +14,8 @@
 import org.spongepowered.asm.mixin.injection.Inject;
 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
 
-import net.minecraft.client.gui.screen.DirectConnectScreen;
 import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screen.multiplayer.DirectConnectScreen;
 import net.minecraft.client.network.ServerInfo;
 import net.minecraft.text.Text;
 import net.wurstclient.WurstClient;
diff --git a/src/main/java/net/wurstclient/mixin/MinecraftClientMixin.java b/src/main/java/net/wurstclient/mixin/MinecraftClientMixin.java
index c12af4285f..4020cdcc4c 100644
--- a/src/main/java/net/wurstclient/mixin/MinecraftClientMixin.java
+++ b/src/main/java/net/wurstclient/mixin/MinecraftClientMixin.java
@@ -19,7 +19,6 @@
 import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
 
 import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.exceptions.AuthenticationException;
 import com.mojang.authlib.minecraft.UserApiService;
 import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
 
@@ -179,23 +178,10 @@ public void setSession(Session session)
 	{
 		wurstSession = session;
 		
-		UserApiService userApiService =
-			wurst_createUserApiService(session.getAccessToken());
+		UserApiService userApiService = authenticationService
+			.createUserApiService(session.getAccessToken());
 		UUID uuid = wurstSession.getUuidOrNull();
 		wurstProfileKeys =
 			new ProfileKeysImpl(userApiService, uuid, runDirectory.toPath());
 	}
-	
-	private UserApiService wurst_createUserApiService(String accessToken)
-	{
-		try
-		{
-			return authenticationService.createUserApiService(accessToken);
-			
-		}catch(AuthenticationException e)
-		{
-			e.printStackTrace();
-			return UserApiService.OFFLINE;
-		}
-	}
 }
diff --git a/src/main/java/net/wurstclient/mixin/PlayerSkinProviderMixin.java b/src/main/java/net/wurstclient/mixin/PlayerSkinProviderMixin.java
index 1525253985..69b7695923 100644
--- a/src/main/java/net/wurstclient/mixin/PlayerSkinProviderMixin.java
+++ b/src/main/java/net/wurstclient/mixin/PlayerSkinProviderMixin.java
@@ -9,6 +9,7 @@
 
 import java.io.InputStreamReader;
 import java.net.URL;
+import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 
 import org.spongepowered.asm.mixin.Mixin;
@@ -19,11 +20,10 @@
 
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
-import com.mojang.authlib.GameProfile;
 import com.mojang.authlib.minecraft.MinecraftProfileTexture;
+import com.mojang.authlib.minecraft.MinecraftProfileTextures;
 
 import net.minecraft.client.texture.PlayerSkinProvider;
-import net.minecraft.client.texture.PlayerSkinProvider.Textures;
 import net.minecraft.client.util.SkinTextures;
 
 @Mixin(PlayerSkinProvider.class)
@@ -33,26 +33,21 @@ public abstract class PlayerSkinProviderMixin
 	private MinecraftProfileTexture currentCape;
 	
 	@Inject(at = @At("HEAD"),
-		method = "fetchSkinTextures(Lcom/mojang/authlib/GameProfile;Lnet/minecraft/client/texture/PlayerSkinProvider$Textures;)Ljava/util/concurrent/CompletableFuture;")
-	private void onFetchSkinTextures(GameProfile profile, Textures textures,
+		method = "fetchSkinTextures(Ljava/util/UUID;Lcom/mojang/authlib/minecraft/MinecraftProfileTextures;)Ljava/util/concurrent/CompletableFuture;")
+	private void onFetchSkinTextures(UUID uuid,
+		MinecraftProfileTextures textures,
 		CallbackInfoReturnable<CompletableFuture<SkinTextures>> cir)
 	{
-		String name = profile.getName();
-		String uuid = profile.getId().toString();
+		String uuidString = uuid.toString();
 		
 		try
 		{
 			if(capes == null)
 				setupWurstCapes();
 			
-			if(capes.has(name))
+			if(capes.has(uuidString))
 			{
-				String capeURL = capes.get(name).getAsString();
-				currentCape = new MinecraftProfileTexture(capeURL, null);
-				
-			}else if(capes.has(uuid))
-			{
-				String capeURL = capes.get(uuid).getAsString();
+				String capeURL = capes.get(uuidString).getAsString();
 				currentCape = new MinecraftProfileTexture(capeURL, null);
 				
 			}else
@@ -60,15 +55,15 @@ private void onFetchSkinTextures(GameProfile profile, Textures textures,
 			
 		}catch(Exception e)
 		{
-			System.err.println("[Wurst] Failed to load cape for '" + name
-				+ "' (" + uuid + ")");
+			System.err
+				.println("[Wurst] Failed to load cape for UUID " + uuidString);
 			
 			e.printStackTrace();
 		}
 	}
 	
 	@ModifyVariable(at = @At("STORE"),
-		method = "fetchSkinTextures(Lcom/mojang/authlib/GameProfile;Lnet/minecraft/client/texture/PlayerSkinProvider$Textures;)Ljava/util/concurrent/CompletableFuture;",
+		method = "fetchSkinTextures(Ljava/util/UUID;Lcom/mojang/authlib/minecraft/MinecraftProfileTextures;)Ljava/util/concurrent/CompletableFuture;",
 		ordinal = 1,
 		name = "minecraftProfileTexture2")
 	private MinecraftProfileTexture modifyCapeTexture(
diff --git a/src/main/java/net/wurstclient/nochatreports/ForcedChatReportsScreen.java b/src/main/java/net/wurstclient/nochatreports/ForcedChatReportsScreen.java
index 98cc86ddce..1ebe7fb415 100644
--- a/src/main/java/net/wurstclient/nochatreports/ForcedChatReportsScreen.java
+++ b/src/main/java/net/wurstclient/nochatreports/ForcedChatReportsScreen.java
@@ -16,7 +16,7 @@
 import net.minecraft.client.gui.Drawable;
 import net.minecraft.client.gui.screen.Screen;
 import net.minecraft.client.gui.widget.ButtonWidget;
-import net.minecraft.text.LiteralTextContent;
+import net.minecraft.text.PlainTextContent.Literal;
 import net.minecraft.text.Text;
 import net.minecraft.text.TranslatableTextContent;
 import net.wurstclient.WurstClient;
@@ -134,7 +134,7 @@ public static boolean isCausedByNoChatReports(Text disconnectReason)
 			&& TRANSLATABLE_DISCONNECT_REASONS.contains(tr.getKey()))
 			return true;
 		
-		if(disconnectReason.getContent() instanceof LiteralTextContent lt
+		if(disconnectReason.getContent() instanceof Literal lt
 			&& LITERAL_DISCONNECT_REASONS.contains(lt.string()))
 			return true;
 		
diff --git a/src/main/java/net/wurstclient/util/LastServerRememberer.java b/src/main/java/net/wurstclient/util/LastServerRememberer.java
index 2ac7eedef7..28b5b88f60 100644
--- a/src/main/java/net/wurstclient/util/LastServerRememberer.java
+++ b/src/main/java/net/wurstclient/util/LastServerRememberer.java
@@ -7,8 +7,8 @@
  */
 package net.wurstclient.util;
 
-import net.minecraft.client.gui.screen.ConnectScreen;
 import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screen.multiplayer.ConnectScreen;
 import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
 import net.minecraft.client.network.ServerAddress;
 import net.minecraft.client.network.ServerInfo;
diff --git a/src/main/resources/assets/wurst/lang/en_us.json b/src/main/resources/assets/wurst/lang/en_us.json
index 21ff899a8a..38f9281583 100644
--- a/src/main/resources/assets/wurst/lang/en_us.json
+++ b/src/main/resources/assets/wurst/lang/en_us.json
@@ -46,7 +46,7 @@
   "description.wurst.hack.autotool": "Automatically equips the fastest applicable tool in your hotbar when you try to break a block.",
   "description.wurst.hack.autototem": "Automatically moves totems of undying to your off-hand.",
   "description.wurst.hack.autowalk": "Makes you walk automatically.",
-  "description.wurst.hack.barrieresp": "Allows you to see nearby barrier blocks.\n\nNote: Due to Minecraft bug MC-47607, this hack does not work if your \"Particles\" option is set to \"Minimal\".",
+  "description.wurst.hack.barrieresp": "Allows you to see nearby barrier blocks.",
   "description.wurst.hack.basefinder": "Finds player bases by searching for man-made blocks.\nThe blocks that it finds will be highlighted in the selected color.\nGood for finding faction bases.",
   "description.wurst.hack.blink": "Suspends all motion updates while enabled.",
   "description.wurst.hack.boatfly": "Allows you to fly with boats and other vehicles.\nPress the sprint key to go down faster.",
diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json
index 09a82d85c3..827d585e69 100644
--- a/src/main/resources/fabric.mod.json
+++ b/src/main/resources/fabric.mod.json
@@ -30,8 +30,8 @@
 
   "depends": {
     "fabricloader": ">=0.15.0",
-    "fabric-api": ">=0.88.4",
-    "minecraft": "~1.20.2-beta.4",
+    "fabric-api": ">=0.91.1",
+    "minecraft": "~1.20.3-beta.3",
     "java": ">=17"
   },
   "suggests": {
diff --git a/src/main/resources/wurst.accesswidener b/src/main/resources/wurst.accesswidener
index 83369db15f..6961e92ae3 100644
--- a/src/main/resources/wurst.accesswidener
+++ b/src/main/resources/wurst.accesswidener
@@ -1,6 +1,5 @@
 accessWidener	v1	named
 accessible	class	net/minecraft/client/render/BackgroundRenderer$StatusEffectFogModifier
-accessible	class	net/minecraft/client/texture/PlayerSkinProvider$Textures
 accessible	method	net/minecraft/client/MinecraftClient	doItemUse	()V
 accessible	method	net/minecraft/client/render/GameRenderer	loadPostProcessor	(Lnet/minecraft/util/Identifier;)V
 accessible	method	net/minecraft/entity/projectile/FishingBobberEntity	isOpenOrWaterAround	(Lnet/minecraft/util/math/BlockPos;)Z