diff --git a/gateway/EaglercraftXBungee/EaglerXBungee-Latest.jar b/gateway/EaglercraftXBungee/EaglerXBungee-Latest.jar
index bdcef2ed..a5d8bef9 100644
Binary files a/gateway/EaglercraftXBungee/EaglerXBungee-Latest.jar and b/gateway/EaglercraftXBungee/EaglerXBungee-Latest.jar differ
diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/EaglerXBungee.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/EaglerXBungee.java
index 126d1119..b69cbe8a 100644
--- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/EaglerXBungee.java
+++ b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/EaglerXBungee.java
@@ -64,8 +64,11 @@ import net.md_5.bungee.BungeeCord;
  */
 public class EaglerXBungee extends Plugin {
 
-	public static final String NATIVE_BUNGEECORD_BUILD = "1.21-R0.1-SNAPSHOT:20a71b0:1887";
-	public static final String NATIVE_WATERFALL_BUILD = "1.21-R0.1-SNAPSHOT:bf1be7e:581";
+	public static final String NATIVE_BUNGEECORD_BUILD = "1.21-R0.1-SNAPSHOT:1265a99:1892";
+	public static final String NATIVE_BUNGEECORD_BUILD_DL = "https://ci.md-5.net/job/BungeeCord/1892/artifact/bootstrap/target/BungeeCord.jar";
+	
+	public static final String NATIVE_WATERFALL_BUILD = "1.21-R0.1-SNAPSHOT:9ab9e2b:582";
+	public static final String NATIVE_WATERFALL_BUILD_DL = "https://api.papermc.io/v2/projects/waterfall/versions/1.21/builds/582/downloads/waterfall-1.21-582.jar";
 	
 	static {
 		CompatWarning.displayCompatWarning();
diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/AuthLoadingCache.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/AuthLoadingCache.java
index 957942a8..852e9d67 100644
--- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/AuthLoadingCache.java
+++ b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/auth/AuthLoadingCache.java
@@ -4,6 +4,8 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.api.EaglerXBungeeAPIHelper;
 
@@ -44,6 +46,7 @@ public class AuthLoadingCache<K, V> {
 		boolean shouldEvict(K key, V value);
 	}
 
+	private final ReadWriteLock cacheMapLock;
 	private final Map<K, CacheEntry<V>> cacheMap;
 	private final CacheLoader<K, V> provider;
 	private final long cacheTTL;
@@ -51,6 +54,7 @@ public class AuthLoadingCache<K, V> {
 	private long cacheTimer;
 
 	public AuthLoadingCache(CacheLoader<K, V> provider, long cacheTTL) {
+		this.cacheMapLock = new ReentrantReadWriteLock();
 		this.cacheMap = new HashMap<>();
 		this.provider = provider;
 		this.cacheTTL = cacheTTL;
@@ -58,13 +62,19 @@ public class AuthLoadingCache<K, V> {
 
 	public V get(K key) {
 		CacheEntry<V> etr;
-		synchronized(cacheMap) {
+		cacheMapLock.readLock().lock();
+		try {
 			etr = cacheMap.get(key);
+		}finally {
+			cacheMapLock.readLock().unlock();
 		}
 		if(etr == null) {
+			cacheMapLock.writeLock().lock();
 			V loaded = provider.load(key);
-			synchronized(cacheMap) {
+			try {
 				cacheMap.put(key, new CacheEntry<>(loaded));
+			}finally {
+				cacheMapLock.writeLock().unlock();
 			}
 			return loaded;
 		}else {
@@ -74,13 +84,17 @@ public class AuthLoadingCache<K, V> {
 	}
 
 	public void evict(K key) {
-		synchronized(cacheMap) {
+		cacheMapLock.writeLock().lock();
+		try {
 			cacheMap.remove(key);
+		}finally {
+			cacheMapLock.writeLock().unlock();
 		}
 	}
 
 	public void evictAll(CacheVisitor<K, V> visitor) {
-		synchronized(cacheMap) {
+		cacheMapLock.writeLock().lock();
+		try {
 			Iterator<Entry<K,CacheEntry<V>>> itr = cacheMap.entrySet().iterator();
 			while(itr.hasNext()) {
 				Entry<K,CacheEntry<V>> etr = itr.next();
@@ -88,6 +102,8 @@ public class AuthLoadingCache<K, V> {
 					itr.remove();
 				}
 			}
+		}finally {
+			cacheMapLock.writeLock().unlock();
 		}
 	}
 
@@ -95,7 +111,8 @@ public class AuthLoadingCache<K, V> {
 		long millis = EaglerXBungeeAPIHelper.steadyTimeMillis();
 		if(millis - cacheTimer > (cacheTTL / 2L)) {
 			cacheTimer = millis;
-			synchronized(cacheMap) {
+			cacheMapLock.writeLock().lock();
+			try {
 				Iterator<CacheEntry<V>> mapItr = cacheMap.values().iterator();
 				while(mapItr.hasNext()) {
 					CacheEntry<V> etr = mapItr.next();
@@ -103,13 +120,18 @@ public class AuthLoadingCache<K, V> {
 						mapItr.remove();
 					}
 				}
+			}finally {
+				cacheMapLock.writeLock().unlock();
 			}
 		}
 	}
 
 	public void flush() {
-		synchronized(cacheMap) {
+		cacheMapLock.writeLock().lock();
+		try {
 			cacheMap.clear();
+		}finally {
+			cacheMapLock.writeLock().unlock();
 		}
 	}
 
diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/protocol/GameProtocolMessageController.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/protocol/GameProtocolMessageController.java
index 1f0d610c..0c8b38db 100644
--- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/protocol/GameProtocolMessageController.java
+++ b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/protocol/GameProtocolMessageController.java
@@ -1,6 +1,7 @@
 package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.protocol;
 
 import java.io.IOException;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.Callable;
@@ -238,10 +239,12 @@ public class GameProtocolMessageController {
 			while(!sendQueueV4.isEmpty()) {
 				sendCount = 0;
 				totalLen = 0;
+				Iterator<byte[]> itr = sendQueueV4.iterator();
 				do {
-					i = sendQueueV4.get(sendCount++).length;
+					i = itr.next().length;
 					totalLen += GamePacketOutputBuffer.getVarIntSize(i) + i;
-				}while(totalLen < 32760 && sendCount < sendQueueV4.size());
+					++sendCount;
+				}while(totalLen < 32760 && itr.hasNext());
 				if(totalLen >= 32760) {
 					--sendCount;
 				}
diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/web/HttpWebServer.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/web/HttpWebServer.java
index 704fbfd3..63848b29 100644
--- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/web/HttpWebServer.java
+++ b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/server/web/HttpWebServer.java
@@ -40,7 +40,6 @@ public class HttpWebServer {
 	private final String page404;
 	private static HttpMemoryCache default404Page;
 	private static HttpMemoryCache default404UpgradePage;
-	private static final Object cacheClearLock = new Object();
 	
 	public HttpWebServer(File directory, Map<String,HttpContentType> contentTypes, List<String> index, String page404) {
 		this.directory = directory;
@@ -52,15 +51,13 @@ public class HttpWebServer {
 	
 	public void flushCache() {
 		long millis = EaglerXBungeeAPIHelper.steadyTimeMillis();
-		synchronized(cacheClearLock) {
-			synchronized(filesCache) {
-				Iterator<HttpMemoryCache> itr = filesCache.values().iterator();
-				while(itr.hasNext()) {
-					HttpMemoryCache i = itr.next();
-					if(i.contentType.fileBrowserCacheTTL != Long.MAX_VALUE && millis - i.lastCacheHit > 900000l) {
-						i.fileData.release();
-						itr.remove();
-					}
+		synchronized(filesCache) {
+			Iterator<HttpMemoryCache> itr = filesCache.values().iterator();
+			while(itr.hasNext()) {
+				HttpMemoryCache i = itr.next();
+				if(i.contentType.fileBrowserCacheTTL != Long.MAX_VALUE && millis - i.lastCacheHit > 900000l) {
+					i.fileData.release();
+					itr.remove();
 				}
 			}
 		}
@@ -94,19 +91,16 @@ public class HttpWebServer {
 			
 			String joinedPath = String.join("/", pathList);
 	
-			synchronized(cacheClearLock) {
-				synchronized(filesCache) {
-					cached = filesCache.get(joinedPath);
-				}
+			//TODO: Rewrite this to cause less lock contention
+			synchronized(filesCache) {
+				cached = filesCache.get(joinedPath);
 				
 				if(cached != null) {
 					cached = validateCache(cached);
 					if(cached != null) {
 						return cached;
 					}else {
-						synchronized(filesCache) {
-							filesCache.remove(joinedPath);
-						}
+						filesCache.remove(joinedPath);
 					}
 				}
 				
@@ -123,19 +117,13 @@ public class HttpWebServer {
 				if(f.isDirectory()) {
 					for(int i = 0, l = index.size(); i < l; ++i) {
 						String p = joinedPath + "/" + index.get(i);
-						synchronized(filesCache) {
-							cached = filesCache.get(p);
-						}
+						cached = filesCache.get(p);
 						if(cached != null) {
 							cached = validateCache(cached);
 							if(cached != null) {
-								synchronized(filesCache) {
-									filesCache.put(joinedPath, cached);
-								}
+								filesCache.put(joinedPath, cached);
 							}else {
-								synchronized(filesCache) {
-									filesCache.remove(p);
-								}
+								filesCache.remove(p);
 								if(page404 == null || path.equals(page404)) {
 									return default404Page;
 								}else {
@@ -151,9 +139,7 @@ public class HttpWebServer {
 						if(ff.isFile()) {
 							HttpMemoryCache memCache = retrieveFile(ff, p);
 							if(memCache != null) {
-								synchronized(filesCache) {
-									filesCache.put(joinedPath, memCache);
-								}
+								filesCache.put(joinedPath, memCache);
 								return memCache;
 							}
 						}
@@ -166,9 +152,7 @@ public class HttpWebServer {
 				}else {
 					HttpMemoryCache memCache = retrieveFile(f, joinedPath);
 					if(memCache != null) {
-						synchronized(filesCache) {
-							filesCache.put(joinedPath, memCache);
-						}
+						filesCache.put(joinedPath, memCache);
 						return memCache;
 					}else {
 						if(page404 == null || path.equals(page404)) {
diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/shit/CompatWarning.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/shit/CompatWarning.java
index 2cdff345..de7fb944 100644
--- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/shit/CompatWarning.java
+++ b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/shit/CompatWarning.java
@@ -37,7 +37,10 @@ public class CompatWarning {
 				":>  apart from the versions listed below:",
 				":>  ",
 				":>  - BungeeCord: " + EaglerXBungee.NATIVE_BUNGEECORD_BUILD,
+				":>  - " + EaglerXBungee.NATIVE_BUNGEECORD_BUILD_DL,
+				":>  ",
 				":>  - Waterfall: " + EaglerXBungee.NATIVE_WATERFALL_BUILD,
+				":>  - " + EaglerXBungee.NATIVE_WATERFALL_BUILD_DL,
 				":>  ",
 				":>  This is not a Bukkit/Spigot plugin!",
 				":>  ",
diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/CapeServiceOffline.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/CapeServiceOffline.java
index 5430bb85..da01d3f2 100644
--- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/CapeServiceOffline.java
+++ b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/CapeServiceOffline.java
@@ -1,8 +1,8 @@
 package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins;
 
-import java.util.HashMap;
-import java.util.Map;
 import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler;
 import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket;
@@ -13,7 +13,7 @@ import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCape
 import net.md_5.bungee.UserConnection;
 
 /**
- * Copyright (c) 2024 lax1dude. All Rights Reserved.
+ * Copyright (c) 2024-2025 lax1dude. All Rights Reserved.
  * 
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@@ -31,21 +31,16 @@ public class CapeServiceOffline {
 
 	public static final int masterRateLimitPerPlayer = 250;
 
-	private final Map<UUID, GameMessagePacket> capesCache = new HashMap<>();
+	private final ConcurrentMap<UUID, GameMessagePacket> capesCache = new ConcurrentHashMap<>();
 
 	public void registerEaglercraftPlayer(UUID playerUUID, GameMessagePacket capePacket) {
-		synchronized(capesCache) {
-			capesCache.put(playerUUID, capePacket);
-		}
+		capesCache.put(playerUUID, capePacket);
 	}
 
 	public void processGetOtherCape(UUID searchUUID, UserConnection sender) {
 		EaglerInitialHandler initialHandler = (EaglerInitialHandler)sender.getPendingConnection();
 		if(initialHandler.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) {
-			GameMessagePacket maybeCape;
-			synchronized(capesCache) {
-				maybeCape = capesCache.get(searchUUID);
-			}
+			GameMessagePacket maybeCape = capesCache.get(searchUUID);
 			if(maybeCape != null) {
 				initialHandler.sendEaglerMessage(maybeCape);
 			}else {
@@ -56,10 +51,7 @@ public class CapeServiceOffline {
 	}
 
 	public void processForceCape(UUID clientUUID, EaglerInitialHandler initialHandler) {
-		GameMessagePacket maybeCape;
-		synchronized(capesCache) {
-			maybeCape = capesCache.get(clientUUID);
-		}
+		GameMessagePacket maybeCape = capesCache.get(clientUUID);
 		if(maybeCape != null) {
 			if (maybeCape instanceof SPacketOtherCapePresetEAG) {
 				initialHandler.sendEaglerMessage(
@@ -72,15 +64,11 @@ public class CapeServiceOffline {
 	}
 
 	public void unregisterPlayer(UUID playerUUID) {
-		synchronized(capesCache) {
-			capesCache.remove(playerUUID);
-		}
+		capesCache.remove(playerUUID);
 	}
 
 	public GameMessagePacket getCape(UUID clientUUID) {
-		synchronized(capesCache) {
-			return capesCache.get(clientUUID);
-		}
+		return capesCache.get(clientUUID);
 	}
 
 	public byte[] getCapeHandshakeData(UUID clientUUID) {
@@ -109,8 +97,6 @@ public class CapeServiceOffline {
 	}
 
 	public void shutdown() {
-		synchronized(capesCache) {
-			capesCache.clear();
-		}
+		capesCache.clear();
 	}
 }
diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinService.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinService.java
index 3d4c5331..d5b30c89 100644
--- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinService.java
+++ b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinService.java
@@ -1,6 +1,7 @@
 package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins;
 
 import java.net.URI;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -10,6 +11,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.function.Consumer;
 import org.apache.commons.codec.binary.Base64;
 
@@ -38,7 +43,7 @@ import net.md_5.bungee.connection.LoginResult;
 import net.md_5.bungee.protocol.Property;
 
 /**
- * Copyright (c) 2022-2024 lax1dude. All Rights Reserved.
+ * Copyright (c) 2022-2025 lax1dude. All Rights Reserved.
  * 
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@@ -56,16 +61,20 @@ public class SkinService implements ISkinService {
 
 	public static final int masterRateLimitPerPlayer = 250;
 
-	private final Map<UUID, CachedPlayerSkin> onlinePlayersCache = new HashMap<>();
+	private final ConcurrentMap<UUID, CachedPlayerSkin> onlinePlayersCache = new ConcurrentHashMap<>();
+	private final ConcurrentMap<UUID, UUID> onlinePlayersToTexturesMap = new ConcurrentHashMap<>();
+	private final ConcurrentMap<UUID, CachedForeignSkin> foreignSkinCache = new ConcurrentHashMap<>();
+
+	private final ReadWriteLock onlinePlayersFromTexturesMapLock = new ReentrantReadWriteLock();
 	private final Multimap<UUID, UUID> onlinePlayersFromTexturesMap = MultimapBuilder.hashKeys().hashSetValues().build();
-	private final Map<UUID, UUID> onlinePlayersToTexturesMap = new HashMap<>();
-	private final Map<UUID, CachedForeignSkin> foreignSkinCache = new HashMap<>();
 
 	private final Map<UUID, PendingTextureDownload> pendingTextures = new HashMap<>();
 	private final Map<UUID, PendingProfileUUIDLookup> pendingUUIDs = new HashMap<>();
 	private final Map<String, PendingProfileNameLookup> pendingNameLookups = new HashMap<>();
 
+	private final ReadWriteLock antagonistsLock = new ReentrantReadWriteLock();
 	private final TObjectIntMap<UUID> antagonists = new TObjectIntHashMap<>();
+
 	private long antagonistCooldown = EaglerXBungeeAPIHelper.steadyTimeMillis();
 
 	private final Consumer<Set<UUID>> antagonistLogger = new Consumer<Set<UUID>>() {
@@ -75,7 +84,8 @@ public class SkinService implements ISkinService {
 			if(t.size() == 1) {
 				int limit = EaglerXBungee.getEagler().getConfig().getAntagonistsRateLimit() << 1;
 				UUID offender = t.iterator().next();
-				synchronized(antagonists) {
+				antagonistsLock.writeLock().lock();
+				try {
 					int v = antagonists.get(offender);
 					if(v == antagonists.getNoEntryValue()) {
 						antagonists.put(offender, 1);
@@ -84,6 +94,8 @@ public class SkinService implements ISkinService {
 							antagonists.put(offender, v + 1);
 						}
 					}
+				}finally {
+					antagonistsLock.writeLock().unlock();
 				}
 			}
 		}
@@ -97,7 +109,7 @@ public class SkinService implements ISkinService {
 		protected final UUID uuid;
 		protected final SkinPacketVersionCache data;
 		protected final int modelKnown;
-		protected long lastHit;
+		protected volatile long lastHit;
 
 		protected CachedForeignSkin(UUID uuid, SkinPacketVersionCache data, int modelKnown) {
 			this.uuid = uuid;
@@ -132,7 +144,7 @@ public class SkinService implements ISkinService {
 		protected final Consumer<Set<UUID>> antagonistsCallback;
 
 		protected final long initializedTime;
-		protected boolean finalized;
+		protected volatile boolean finalized;
 
 		protected PendingTextureDownload(UUID textureUUID, String textureURL, UUID caller, Consumer<byte[]> callback,
 				Consumer<Set<UUID>> antagonistsCallback) {
@@ -174,7 +186,7 @@ public class SkinService implements ISkinService {
 		protected final Consumer<Set<UUID>> antagonistsCallback;
 
 		protected final long initializedTime;
-		protected boolean finalized;
+		protected volatile boolean finalized;
 
 		protected PendingProfileUUIDLookup(UUID profileUUID, UUID caller, Consumer<CacheFetchedProfile> callback,
 				Consumer<Set<UUID>> antagonistsCallback) {
@@ -215,7 +227,7 @@ public class SkinService implements ISkinService {
 		protected final Consumer<Set<UUID>> antagonistsCallback;
 
 		protected final long initializedTime;
-		protected boolean finalized;
+		protected volatile boolean finalized;
 
 		protected PendingProfileNameLookup(String profileName, UUID caller, Consumer<CacheFetchedProfile> callback,
 				Consumer<Set<UUID>> antagonistsCallback) {
@@ -263,60 +275,46 @@ public class SkinService implements ISkinService {
 			return;
 		}
 		
-		CachedPlayerSkin maybeCachedPacket;
-		synchronized(onlinePlayersCache) {
-			maybeCachedPacket = onlinePlayersCache.get(searchUUID);
-		}
+		CachedPlayerSkin maybeCachedPacket = onlinePlayersCache.get(searchUUID);
 		
 		if(maybeCachedPacket != null) {
 			eaglerHandler.sendEaglerMessage(maybeCachedPacket.data.get(eaglerHandler.getEaglerProtocol()));
 		}else {
 			ProxiedPlayer player = BungeeCord.getInstance().getPlayer(searchUUID);
-			UUID playerTexture;
-			synchronized(onlinePlayersToTexturesMap) {
-				playerTexture = onlinePlayersToTexturesMap.get(searchUUID);
-			}
+			UUID playerTexture = onlinePlayersToTexturesMap.get(searchUUID);
 			if(playerTexture != null) {
 				Collection<UUID> possiblePlayers;
-				synchronized(onlinePlayersFromTexturesMap) {
-					possiblePlayers = onlinePlayersFromTexturesMap.get(playerTexture);
+				onlinePlayersFromTexturesMapLock.readLock().lock();
+				try {
+					possiblePlayers = new ArrayList<>(onlinePlayersFromTexturesMap.get(playerTexture));
+				}finally {
+					onlinePlayersFromTexturesMapLock.readLock().unlock();
 				}
 				boolean playersExist = possiblePlayers.size() > 0;
 				if(playersExist) {
 					for(UUID uuid : possiblePlayers) {
-						synchronized(onlinePlayersCache) {
-							maybeCachedPacket = onlinePlayersCache.get(uuid);
-						}
+						maybeCachedPacket = onlinePlayersCache.get(uuid);
 						if(maybeCachedPacket != null) {
 							SkinPacketVersionCache rewritten = SkinPacketVersionCache.rewriteUUID(
 									maybeCachedPacket.data, searchUUID.getMostSignificantBits(),
 									searchUUID.getLeastSignificantBits());
 							if(player != null) {
-								synchronized(onlinePlayersCache) {
-									onlinePlayersCache.put(searchUUID, new CachedPlayerSkin(rewritten,
-											maybeCachedPacket.textureUUID, maybeCachedPacket.modelId));
-								}
+								onlinePlayersCache.put(searchUUID, new CachedPlayerSkin(rewritten,
+										maybeCachedPacket.textureUUID, maybeCachedPacket.modelId));
 							}
 							eaglerHandler.sendEaglerMessage(rewritten.get(eaglerHandler.getEaglerProtocol()));
 							return;
 						}
 					}
 				}
-				CachedForeignSkin foreignSkin;
-				synchronized(foreignSkinCache) {
-					foreignSkin = foreignSkinCache.get(playerTexture);
-				}
+				CachedForeignSkin foreignSkin = foreignSkinCache.get(playerTexture);
 				if(foreignSkin != null && foreignSkin.modelKnown != -1) {
 					if(player != null) {
-						synchronized(onlinePlayersCache) {
-							onlinePlayersCache.put(searchUUID,
-									new CachedPlayerSkin(SkinPacketVersionCache.rewriteUUID(foreignSkin.data,
-											searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits()),
-											playerTexture, foreignSkin.modelKnown));
-						}
-						synchronized(foreignSkinCache) {
-							foreignSkinCache.remove(playerTexture);
-						}
+						onlinePlayersCache.put(searchUUID,
+								new CachedPlayerSkin(SkinPacketVersionCache.rewriteUUID(foreignSkin.data,
+										searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits()),
+										playerTexture, foreignSkin.modelKnown));
+						foreignSkinCache.remove(playerTexture);
 					}else {
 						foreignSkin.lastHit = EaglerXBungeeAPIHelper.steadyTimeMillis();
 					}
@@ -339,7 +337,7 @@ public class SkinService implements ISkinService {
 									if(skinObj != null) {
 										JsonElement url = json.get("url");
 										if(url != null) {
-											String urlStr = SkinService.sanitizeTextureURL(url.getAsString());
+											String urlStr = sanitizeTextureURL(url.getAsString());
 											if(urlStr == null) {
 												break;
 											}
@@ -353,19 +351,14 @@ public class SkinService implements ISkinService {
 											}
 											UUID skinUUID = SkinPackets.createEaglerURLSkinUUID(urlStr);
 											
-											CachedForeignSkin foreignSkin;
-											synchronized(foreignSkinCache) {
-												foreignSkin = foreignSkinCache.remove(skinUUID);
-											}
+											CachedForeignSkin foreignSkin = foreignSkinCache.remove(skinUUID);
 											if(foreignSkin != null) {
 												registerTextureToPlayerAssociation(skinUUID, searchUUID);
 												SkinPacketVersionCache rewrite = SkinPacketVersionCache
 														.rewriteUUIDModel(foreignSkin.data,
 																searchUUID.getMostSignificantBits(),
 																searchUUID.getLeastSignificantBits(), model);
-												synchronized(onlinePlayersCache) {
-													onlinePlayersCache.put(searchUUID, new CachedPlayerSkin(rewrite, skinUUID, model));
-												}
+												onlinePlayersCache.put(searchUUID, new CachedPlayerSkin(rewrite, skinUUID, model));
 												eaglerHandler.sendEaglerMessage(rewrite.get(eaglerHandler.getEaglerProtocol()));
 												return;
 											}
@@ -398,10 +391,7 @@ public class SkinService implements ISkinService {
 					});
 				}
 			}else {
-				CachedForeignSkin foreignSkin;
-				synchronized(foreignSkinCache) {
-					foreignSkin = foreignSkinCache.get(searchUUID);
-				}
+				CachedForeignSkin foreignSkin = foreignSkinCache.get(searchUUID);
 				if(foreignSkin != null) {
 					foreignSkin.lastHit = EaglerXBungeeAPIHelper.steadyTimeMillis();
 					eaglerHandler.sendEaglerMessage(foreignSkin.data.get(eaglerHandler.getEaglerProtocol()));
@@ -430,25 +420,22 @@ public class SkinService implements ISkinService {
 		if(!eaglerHandler.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) {
 			return;
 		}
-		CachedForeignSkin foreignSkin;
-		synchronized(foreignSkinCache) {
-			foreignSkin = foreignSkinCache.get(searchUUID);
-		}
+		CachedForeignSkin foreignSkin = foreignSkinCache.get(searchUUID);
 		if(foreignSkin != null) {
 			foreignSkin.lastHit = EaglerXBungeeAPIHelper.steadyTimeMillis();
 			eaglerHandler.sendEaglerMessage(foreignSkin.data.get(eaglerHandler.getEaglerProtocol()));
 		}else {
 			Collection<UUID> possiblePlayers;
-			synchronized(onlinePlayersFromTexturesMap) {
-				possiblePlayers = onlinePlayersFromTexturesMap.get(searchUUID);
+			onlinePlayersFromTexturesMapLock.readLock().lock();
+			try {
+				possiblePlayers = new ArrayList<>(onlinePlayersFromTexturesMap.get(searchUUID));
+			}finally {
+				onlinePlayersFromTexturesMapLock.readLock().unlock();
 			}
 			boolean playersExist = possiblePlayers.size() > 0;
 			if(playersExist) {
 				for(UUID uuid : possiblePlayers) {
-					CachedPlayerSkin maybeCachedPacket;
-					synchronized(onlinePlayersCache) {
-						maybeCachedPacket = onlinePlayersCache.get(uuid);
-					}
+					CachedPlayerSkin maybeCachedPacket = onlinePlayersCache.get(uuid);
 					if(maybeCachedPacket != null) {
 						eaglerHandler.sendEaglerMessage(maybeCachedPacket.data.get(eaglerHandler.getEaglerProtocol(),
 								searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits()));
@@ -461,10 +448,17 @@ public class SkinService implements ISkinService {
 						searchUUID.getLeastSignificantBits(), 0));
 				return;
 			}
-			if(eaglerHandler.skinTextureDownloadRateLimiter.rateLimit(config.getSkinRateLimitPlayer()) && !isLimitedAsAntagonist(sender.getUniqueId())) {
-				doAsync(() -> {
-					processResolveURLTextureForForeign(sender, searchUUID, searchUUID, skinURL, -1);
-				});
+			skinURL = sanitizeTextureURL(skinURL);
+			if(skinURL != null) {
+				final String skinURL_ = skinURL;
+				if(eaglerHandler.skinTextureDownloadRateLimiter.rateLimit(config.getSkinRateLimitPlayer()) && !isLimitedAsAntagonist(sender.getUniqueId())) {
+					doAsync(() -> {
+						processResolveURLTextureForForeign(sender, searchUUID, searchUUID, skinURL_, -1);
+					});
+				}
+			}else {
+				eaglerHandler.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(),
+						searchUUID.getLeastSignificantBits(), 0));
 			}
 		}
 	}
@@ -479,10 +473,7 @@ public class SkinService implements ISkinService {
 
 						@Override
 						public void accept(byte[] t) {
-							CachedPlayerSkin skin;
-							synchronized(onlinePlayersCache) {
-								skin = onlinePlayersCache.get(onlineCacheUUID);
-							}
+							CachedPlayerSkin skin = onlinePlayersCache.get(onlineCacheUUID);
 							if(skin != null) {
 								EaglerInitialHandler initialHandler = (EaglerInitialHandler)initiator.getPendingConnection();
 								initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol()));
@@ -510,9 +501,7 @@ public class SkinService implements ISkinService {
 										onlineCacheUUID.getMostSignificantBits(),
 										onlineCacheUUID.getLeastSignificantBits()), null, -1);
 							}
-							synchronized (onlinePlayersCache) {
-								onlinePlayersCache.put(onlineCacheUUID, skin);
-							}
+							onlinePlayersCache.put(onlineCacheUUID, skin);
 							EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection();
 							initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol()));
 						}
@@ -538,10 +527,7 @@ public class SkinService implements ISkinService {
 
 						@Override
 						public void accept(byte[] t) {
-							CachedForeignSkin skin;
-							synchronized(foreignSkinCache) {
-								skin = foreignSkinCache.get(foreignCacheUUID);
-							}
+							CachedForeignSkin skin = foreignSkinCache.get(foreignCacheUUID);
 							if(skin != null) {
 								EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection();
 								initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol()));
@@ -570,9 +556,7 @@ public class SkinService implements ISkinService {
 												foreignCacheUUID.getLeastSignificantBits()),
 										-1);
 							}
-							synchronized (foreignSkinCache) {
-								foreignSkinCache.put(foreignCacheUUID, skin);
-							}
+							foreignSkinCache.put(foreignCacheUUID, skin);
 							EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection();
 							initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol()));
 						}
@@ -598,10 +582,7 @@ public class SkinService implements ISkinService {
 						@Override
 						public void accept(CacheFetchedProfile t) {
 							if(t == null || t.texture == null) {
-								CachedPlayerSkin skin;
-								synchronized(onlinePlayersCache) {
-									skin = onlinePlayersCache.get(playerUUID);
-								}
+								CachedPlayerSkin skin = onlinePlayersCache.get(playerUUID);
 								if(skin != null) {
 									EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection();
 									initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol()));
@@ -634,9 +615,7 @@ public class SkinService implements ISkinService {
 												SkinPackets.getModelId(t.model) == 1 ? 1 : 0),
 										null, -1);
 							}
-							synchronized(onlinePlayersCache) {
-								onlinePlayersCache.put(playerUUID, skin);
-							}
+							onlinePlayersCache.put(playerUUID, skin);
 							EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection();
 							initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol()));
 						}else {
@@ -666,10 +645,7 @@ public class SkinService implements ISkinService {
 						@Override
 						public void accept(CacheFetchedProfile t) {
 							if(t == null || t.texture == null) {
-								CachedPlayerSkin skin;
-								synchronized(onlinePlayersCache) {
-									skin = onlinePlayersCache.get(t.uuid);
-								}
+								CachedPlayerSkin skin = onlinePlayersCache.get(t.uuid);
 								if(skin != null) {
 									EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection();
 									initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol()));
@@ -700,9 +676,7 @@ public class SkinService implements ISkinService {
 										mapUUID.getMostSignificantBits(), mapUUID.getLeastSignificantBits(),
 										SkinPackets.getModelId(t.model) == 1 ? 1 : 0), null, -1);
 							}
-							synchronized(onlinePlayersCache) {
-								onlinePlayersCache.put(mapUUID, skin);
-							}
+							onlinePlayersCache.put(mapUUID, skin);
 							EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection();
 							initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol()));
 						}else {
@@ -732,10 +706,7 @@ public class SkinService implements ISkinService {
 						@Override
 						public void accept(CacheFetchedProfile t) {
 							if(t == null || t.texture == null) {
-								CachedForeignSkin skin;
-								synchronized(foreignSkinCache) {
-									skin = foreignSkinCache.get(playerUUID);
-								}
+								CachedForeignSkin skin = foreignSkinCache.get(playerUUID);
 								if(skin != null) {
 									EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection();
 									initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol()));
@@ -768,9 +739,7 @@ public class SkinService implements ISkinService {
 												SkinPackets.getModelId(t.model) == 1 ? 1 : 0),
 										-1);
 							}
-							synchronized(foreignSkinCache) {
-								foreignSkinCache.put(playerUUID, skin);
-							}
+							foreignSkinCache.put(playerUUID, skin);
 							EaglerInitialHandler initialHandler = (EaglerInitialHandler) initiator.getPendingConnection();
 							initialHandler.sendEaglerMessage(skin.data.get(initialHandler.getEaglerProtocol()));
 						}else {
@@ -791,27 +760,16 @@ public class SkinService implements ISkinService {
 	}
 	
 	public void registerEaglercraftPlayer(UUID clientUUID, SkinPacketVersionCache generatedPacket, int modelId) {
-		synchronized(foreignSkinCache) {
-			foreignSkinCache.remove(clientUUID);
-		}
-		synchronized(onlinePlayersCache) {
-			onlinePlayersCache.put(clientUUID, new CachedPlayerSkin(generatedPacket, null, modelId));
-		}
+		foreignSkinCache.remove(clientUUID);
+		onlinePlayersCache.put(clientUUID, new CachedPlayerSkin(generatedPacket, null, modelId));
 	}
 	
 	public void unregisterPlayer(UUID clientUUID) {
-		CachedPlayerSkin data;
-		synchronized(onlinePlayersCache) {
-			data = onlinePlayersCache.remove(clientUUID);
-		}
+		CachedPlayerSkin data = onlinePlayersCache.remove(clientUUID);
 		if(data != null) {
-			synchronized(foreignSkinCache) {
-				foreignSkinCache.put(clientUUID, new CachedForeignSkin(clientUUID, data.data, data.modelId));
-			}
+			foreignSkinCache.put(clientUUID, new CachedForeignSkin(clientUUID, data.data, data.modelId));
 			if(data.textureUUID != null) {
-				synchronized(foreignSkinCache) {
-					foreignSkinCache.put(data.textureUUID, new CachedForeignSkin(data.textureUUID, data.data, data.modelId));
-				}
+				foreignSkinCache.put(data.textureUUID, new CachedForeignSkin(data.textureUUID, data.data, data.modelId));
 			}
 			deletePlayerTextureAssociation(clientUUID, data.textureUUID);
 		}else {
@@ -821,94 +779,77 @@ public class SkinService implements ISkinService {
 	
 	private void deletePlayerTextureAssociation(UUID clientUUID, UUID textureUUID) {
 		if(textureUUID != null) {
-			synchronized(onlinePlayersToTexturesMap) {
-				onlinePlayersToTexturesMap.remove(clientUUID);
-			}
-			synchronized(onlinePlayersFromTexturesMap) {
+			onlinePlayersToTexturesMap.remove(clientUUID);
+			onlinePlayersFromTexturesMapLock.writeLock().lock();
+			try {
 				onlinePlayersFromTexturesMap.remove(textureUUID, clientUUID);
+			}finally {
+				onlinePlayersFromTexturesMapLock.writeLock().unlock();
 			}
 		}else {
-			UUID removedUUID;
-			synchronized(onlinePlayersToTexturesMap) {
-				removedUUID = onlinePlayersToTexturesMap.remove(clientUUID);
-			}
+			UUID removedUUID = onlinePlayersToTexturesMap.remove(clientUUID);
 			if(removedUUID != null) {
-				synchronized(onlinePlayersFromTexturesMap) {
+				onlinePlayersFromTexturesMapLock.writeLock().lock();
+				try {
 					onlinePlayersFromTexturesMap.remove(removedUUID, clientUUID);
+				}finally {
+					onlinePlayersFromTexturesMapLock.writeLock().unlock();
 				}
 			}
 		}
 	}
 	
 	public void registerTextureToPlayerAssociation(UUID textureUUID, UUID playerUUID) {
-		synchronized(onlinePlayersFromTexturesMap) {
+		onlinePlayersFromTexturesMapLock.writeLock().lock();
+		try {
 			onlinePlayersFromTexturesMap.put(textureUUID, playerUUID);
+		}finally {
+			onlinePlayersFromTexturesMapLock.writeLock().unlock();
 		}
-		synchronized(onlinePlayersToTexturesMap) {
-			onlinePlayersToTexturesMap.put(playerUUID, textureUUID);
-		}
-		CachedForeignSkin foreign;
-		synchronized(foreignSkinCache) {
-			foreign = foreignSkinCache.remove(textureUUID);
-		}
+		onlinePlayersToTexturesMap.put(playerUUID, textureUUID);
+		CachedForeignSkin foreign = foreignSkinCache.remove(textureUUID);
 		if(foreign != null) {
-			synchronized(onlinePlayersCache) {
-				onlinePlayersCache.put(playerUUID, new CachedPlayerSkin(foreign.data, textureUUID, foreign.modelKnown));
-			}
+			onlinePlayersCache.put(playerUUID, new CachedPlayerSkin(foreign.data, textureUUID, foreign.modelKnown));
 		}
 	}
 
 	public void processForceSkin(UUID playerUUID, EaglerInitialHandler eaglerHandler) {
-		CachedPlayerSkin maybeCachedPacket;
-		synchronized(onlinePlayersCache) {
-			maybeCachedPacket = onlinePlayersCache.get(playerUUID);
-		}
+		CachedPlayerSkin maybeCachedPacket = onlinePlayersCache.get(playerUUID);
 		
 		if(maybeCachedPacket != null) {
 			eaglerHandler.sendEaglerMessage(maybeCachedPacket.data.getForceClientV4());
 		}else {
-			UUID playerTexture;
-			synchronized(onlinePlayersToTexturesMap) {
-				playerTexture = onlinePlayersToTexturesMap.get(playerUUID);
-			}
+			UUID playerTexture = onlinePlayersToTexturesMap.get(playerUUID);
 			if(playerTexture != null) {
 				Collection<UUID> possiblePlayers;
-				synchronized(onlinePlayersFromTexturesMap) {
-					possiblePlayers = onlinePlayersFromTexturesMap.get(playerTexture);
+				onlinePlayersFromTexturesMapLock.readLock().lock();
+				try {
+					possiblePlayers = new ArrayList<>(onlinePlayersFromTexturesMap.get(playerTexture));
+				}finally {
+					onlinePlayersFromTexturesMapLock.readLock().unlock();
 				}
 				boolean playersExist = possiblePlayers.size() > 0;
 				if(playersExist) {
 					for(UUID uuid : possiblePlayers) {
-						synchronized(onlinePlayersCache) {
-							maybeCachedPacket = onlinePlayersCache.get(uuid);
-						}
+						maybeCachedPacket = onlinePlayersCache.get(uuid);
 						if(maybeCachedPacket != null) {
 							SkinPacketVersionCache rewritten = SkinPacketVersionCache.rewriteUUID(
 									maybeCachedPacket.data, playerUUID.getMostSignificantBits(),
 									playerUUID.getLeastSignificantBits());
-							synchronized(onlinePlayersCache) {
-								onlinePlayersCache.put(playerUUID, new CachedPlayerSkin(rewritten,
-										maybeCachedPacket.textureUUID, maybeCachedPacket.modelId));
-							}
+							onlinePlayersCache.put(playerUUID, new CachedPlayerSkin(rewritten,
+									maybeCachedPacket.textureUUID, maybeCachedPacket.modelId));
 							eaglerHandler.sendEaglerMessage(rewritten.getForceClientV4());
 							return;
 						}
 					}
 				}
-				CachedForeignSkin foreignSkin;
-				synchronized(foreignSkinCache) {
-					foreignSkin = foreignSkinCache.get(playerTexture);
-				}
+				CachedForeignSkin foreignSkin = foreignSkinCache.get(playerTexture);
 				if(foreignSkin != null && foreignSkin.modelKnown != -1) {
-					synchronized(onlinePlayersCache) {
-						onlinePlayersCache.put(playerUUID,
-								new CachedPlayerSkin(SkinPacketVersionCache.rewriteUUID(foreignSkin.data,
-										playerUUID.getMostSignificantBits(), playerUUID.getLeastSignificantBits()),
-										playerTexture, foreignSkin.modelKnown));
-					}
-					synchronized(foreignSkinCache) {
-						foreignSkinCache.remove(playerTexture);
-					}
+					onlinePlayersCache.put(playerUUID,
+							new CachedPlayerSkin(SkinPacketVersionCache.rewriteUUID(foreignSkin.data,
+									playerUUID.getMostSignificantBits(), playerUUID.getLeastSignificantBits()),
+									playerTexture, foreignSkin.modelKnown));
+					foreignSkinCache.remove(playerTexture);
 					eaglerHandler.sendEaglerMessage(foreignSkin.data.getForceClientV4());
 					return;
 				}
@@ -927,7 +868,7 @@ public class SkinService implements ISkinService {
 								if(skinObj != null) {
 									JsonElement url = json.get("url");
 									if(url != null) {
-										String urlStr = SkinService.sanitizeTextureURL(url.getAsString());
+										String urlStr = sanitizeTextureURL(url.getAsString());
 										if(urlStr == null) {
 											break;
 										}
@@ -941,19 +882,14 @@ public class SkinService implements ISkinService {
 										}
 										UUID skinUUID = SkinPackets.createEaglerURLSkinUUID(urlStr);
 										
-										CachedForeignSkin foreignSkin;
-										synchronized(foreignSkinCache) {
-											foreignSkin = foreignSkinCache.remove(skinUUID);
-										}
+										CachedForeignSkin foreignSkin = foreignSkinCache.remove(skinUUID);
 										if(foreignSkin != null) {
 											registerTextureToPlayerAssociation(skinUUID, playerUUID);
 											SkinPacketVersionCache rewrite = SkinPacketVersionCache
 													.rewriteUUIDModel(foreignSkin.data,
 															playerUUID.getMostSignificantBits(),
 															playerUUID.getLeastSignificantBits(), model);
-											synchronized(onlinePlayersCache) {
-												onlinePlayersCache.put(playerUUID, new CachedPlayerSkin(rewrite, skinUUID, model));
-											}
+											onlinePlayersCache.put(playerUUID, new CachedPlayerSkin(rewrite, skinUUID, model));
 											eaglerHandler.sendEaglerMessage(rewrite.getForceClientV4());
 											return;
 										}
@@ -981,10 +917,7 @@ public class SkinService implements ISkinService {
 					}
 				});
 			}else {
-				CachedForeignSkin foreignSkin;
-				synchronized(foreignSkinCache) {
-					foreignSkin = foreignSkinCache.get(playerUUID);
-				}
+				CachedForeignSkin foreignSkin = foreignSkinCache.get(playerUUID);
 				if(foreignSkin != null) {
 					foreignSkin.lastHit = EaglerXBungeeAPIHelper.steadyTimeMillis();
 					eaglerHandler.sendEaglerMessage(foreignSkin.data.getForceClientV4());
@@ -1011,10 +944,7 @@ public class SkinService implements ISkinService {
 
 						@Override
 						public void accept(byte[] t) {
-							CachedPlayerSkin skin;
-							synchronized(onlinePlayersCache) {
-								skin = onlinePlayersCache.get(onlineCacheUUID);
-							}
+							CachedPlayerSkin skin = onlinePlayersCache.get(onlineCacheUUID);
 							if(skin != null) {
 								initiator.sendEaglerMessage(skin.data.getForceClientV4());
 							}
@@ -1041,9 +971,7 @@ public class SkinService implements ISkinService {
 										onlineCacheUUID.getMostSignificantBits(),
 										onlineCacheUUID.getLeastSignificantBits()), null, -1);
 							}
-							synchronized (onlinePlayersCache) {
-								onlinePlayersCache.put(onlineCacheUUID, skin);
-							}
+							onlinePlayersCache.put(onlineCacheUUID, skin);
 							initiator.sendEaglerMessage(skin.data.getForceClientV4());
 						}
 
@@ -1068,10 +996,7 @@ public class SkinService implements ISkinService {
 
 						@Override
 						public void accept(byte[] t) {
-							CachedForeignSkin skin;
-							synchronized(foreignSkinCache) {
-								skin = foreignSkinCache.get(foreignCacheUUID);
-							}
+							CachedForeignSkin skin = foreignSkinCache.get(foreignCacheUUID);
 							if(skin != null) {
 								initiator.sendEaglerMessage(skin.data.getForceClientV4());
 							}
@@ -1099,9 +1024,7 @@ public class SkinService implements ISkinService {
 												foreignCacheUUID.getLeastSignificantBits()),
 										-1);
 							}
-							synchronized (foreignSkinCache) {
-								foreignSkinCache.put(foreignCacheUUID, skin);
-							}
+							foreignSkinCache.put(foreignCacheUUID, skin);
 							initiator.sendEaglerMessage(skin.data.getForceClientV4());
 						}
 
@@ -1126,10 +1049,7 @@ public class SkinService implements ISkinService {
 						@Override
 						public void accept(CacheFetchedProfile t) {
 							if(t == null || t.texture == null) {
-								CachedPlayerSkin skin;
-								synchronized(onlinePlayersCache) {
-									skin = onlinePlayersCache.get(playerUUID);
-								}
+								CachedPlayerSkin skin = onlinePlayersCache.get(playerUUID);
 								if(skin != null) {
 									initiator.sendEaglerMessage(skin.data.getForceClientV4());
 								}
@@ -1161,9 +1081,7 @@ public class SkinService implements ISkinService {
 												SkinPackets.getModelId(t.model) == 1 ? 1 : 0),
 										null, -1);
 							}
-							synchronized(onlinePlayersCache) {
-								onlinePlayersCache.put(playerUUID, skin);
-							}
+							onlinePlayersCache.put(playerUUID, skin);
 							initiator.sendEaglerMessage(skin.data.getForceClientV4());
 						}else {
 							processResolveURLTextureForOnlineToForce(initiator, playerUUID, t.textureUUID, t.texture,
@@ -1192,10 +1110,7 @@ public class SkinService implements ISkinService {
 						@Override
 						public void accept(CacheFetchedProfile t) {
 							if(t == null || t.texture == null) {
-								CachedPlayerSkin skin;
-								synchronized(onlinePlayersCache) {
-									skin = onlinePlayersCache.get(t.uuid);
-								}
+								CachedPlayerSkin skin = onlinePlayersCache.get(t.uuid);
 								if(skin != null) {
 									initiator.sendEaglerMessage(skin.data.getForceClientV4());
 								}
@@ -1225,9 +1140,7 @@ public class SkinService implements ISkinService {
 										mapUUID.getMostSignificantBits(), mapUUID.getLeastSignificantBits(),
 										SkinPackets.getModelId(t.model) == 1 ? 1 : 0), null, -1);
 							}
-							synchronized(onlinePlayersCache) {
-								onlinePlayersCache.put(mapUUID, skin);
-							}
+							onlinePlayersCache.put(mapUUID, skin);
 							initiator.sendEaglerMessage(skin.data.getForceClientV4());
 						}else {
 							processResolveURLTextureForOnlineToForce(initiator, mapUUID, t.textureUUID, t.texture,
@@ -1256,10 +1169,7 @@ public class SkinService implements ISkinService {
 						@Override
 						public void accept(CacheFetchedProfile t) {
 							if(t == null || t.texture == null) {
-								CachedForeignSkin skin;
-								synchronized(foreignSkinCache) {
-									skin = foreignSkinCache.get(playerUUID);
-								}
+								CachedForeignSkin skin = foreignSkinCache.get(playerUUID);
 								if(skin != null) {
 									initiator.sendEaglerMessage(skin.data.getForceClientV4());
 								}
@@ -1291,9 +1201,7 @@ public class SkinService implements ISkinService {
 												SkinPackets.getModelId(t.model) == 1 ? 1 : 0),
 										-1);
 							}
-							synchronized(foreignSkinCache) {
-								foreignSkinCache.put(playerUUID, skin);
-							}
+							foreignSkinCache.put(playerUUID, skin);
 							initiator.sendEaglerMessage(skin.data.getForceClientV4());
 						}else {
 							processResolveURLTextureForForeignToForce(initiator, playerUUID, t.textureUUID, t.texture,
@@ -1315,12 +1223,16 @@ public class SkinService implements ISkinService {
 	public void flush() {
 		long millis = EaglerXBungeeAPIHelper.steadyTimeMillis();
 		
-		synchronized(foreignSkinCache) {
-			Iterator<CachedForeignSkin> itr = foreignSkinCache.values().iterator();
-			while(itr.hasNext()) {
-				if(millis - itr.next().lastHit > 900000l) { // 15 minutes
-					itr.remove();
-				}
+		final List<UUID> foreignSkinCleanup = new ArrayList<>(4);
+		foreignSkinCache.entrySet().forEach((etr) -> {
+			if(millis - etr.getValue().lastHit > 900000l) { // 15 minutes
+				foreignSkinCleanup.add(etr.getKey());
+			}
+		});
+		
+		if(!foreignSkinCleanup.isEmpty()) {
+			for(UUID uuid : foreignSkinCleanup) {
+				foreignSkinCache.remove(uuid);
 			}
 		}
 		
@@ -1371,7 +1283,8 @@ public class SkinService implements ISkinService {
 		elapsedCooldown /= cooldownPeriod;
 		if(elapsedCooldown > 0) {
 			antagonistCooldown += elapsedCooldown * cooldownPeriod;
-			synchronized(antagonists) {
+			antagonistsLock.writeLock().lock();
+			try {
 				Iterator<UUID> itr = antagonists.keySet().iterator();
 				while(itr.hasNext()) {
 					UUID key = itr.next();
@@ -1382,6 +1295,8 @@ public class SkinService implements ISkinService {
 						antagonists.put(key, i);
 					}
 				}
+			}finally {
+				antagonistsLock.writeLock().unlock();
 			}
 		}
 		
@@ -1389,10 +1304,7 @@ public class SkinService implements ISkinService {
 	}
 
 	public SkinPacketVersionCache getSkin(UUID playerUUID) {
-		CachedPlayerSkin skin;
-		synchronized(onlinePlayersCache) {
-			skin = onlinePlayersCache.get(playerUUID);
-		}
+		CachedPlayerSkin skin = onlinePlayersCache.get(playerUUID);
 		return skin != null ? skin.data : null;
 	}
 
@@ -1407,25 +1319,26 @@ public class SkinService implements ISkinService {
 	private boolean isLimitedAsAntagonist(UUID uuid) {
 		int limit = EaglerXBungee.getEagler().getConfig().getAntagonistsRateLimit();
 		limit += limit >> 1;
-		synchronized(antagonists) {
-			int i = antagonists.get(uuid);
-			return i != antagonists.getNoEntryValue() && i > limit;
+		int i;
+		antagonistsLock.readLock().lock();
+		try {
+			i = antagonists.get(uuid);
+		}finally {
+			antagonistsLock.readLock().unlock();
 		}
+		return i != antagonists.getNoEntryValue() && i > limit;
 	}
 	
 	private void resetMaps() {
-		synchronized(onlinePlayersCache) {
-			onlinePlayersCache.clear();
-		}
-		synchronized(onlinePlayersFromTexturesMap) {
+		onlinePlayersCache.clear();
+		onlinePlayersFromTexturesMapLock.writeLock().lock();
+		try {
 			onlinePlayersFromTexturesMap.clear();
+		}finally {
+			onlinePlayersFromTexturesMapLock.writeLock().unlock();
 		}
-		synchronized(onlinePlayersToTexturesMap) {
-			onlinePlayersToTexturesMap.clear();
-		}
-		synchronized(foreignSkinCache) {
-			foreignSkinCache.clear();
-		}
+		onlinePlayersToTexturesMap.clear();
+		foreignSkinCache.clear();
 		synchronized(pendingTextures) {
 			pendingTextures.clear();
 		}
@@ -1435,8 +1348,11 @@ public class SkinService implements ISkinService {
 		synchronized(pendingNameLookups) {
 			pendingNameLookups.clear();
 		}
-		synchronized(antagonists) {
+		antagonistsLock.writeLock().lock();
+		try {
 			antagonists.clear();
+		}finally {
+			antagonistsLock.writeLock().unlock();
 		}
 	}
 	
@@ -1453,7 +1369,7 @@ public class SkinService implements ISkinService {
 				return null;
 			}
 			String host = uri.getHost();
-			if(host == null) {
+			if(host == null || !EaglerXBungee.getEagler().getConfig().isValidSkinHost(host)) {
 				return null;
 			}
 			scheme = scheme.toLowerCase();
diff --git a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinServiceOffline.java b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinServiceOffline.java
index 06298908..927acd6f 100644
--- a/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinServiceOffline.java
+++ b/gateway/EaglercraftXBungee/src/main/java/net/lax1dude/eaglercraft/v1_8/plugin/gateway_bungeecord/skins/SkinServiceOffline.java
@@ -1,13 +1,8 @@
 package net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.skins;
 
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
 import java.util.UUID;
-
-import com.google.common.collect.Multimap;
-import com.google.common.collect.MultimapBuilder;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.server.EaglerInitialHandler;
 import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinPresetEAG;
@@ -15,7 +10,7 @@ import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache
 import net.md_5.bungee.UserConnection;
 
 /**
- * Copyright (c) 2022-2023 lax1dude. All Rights Reserved.
+ * Copyright (c) 2022-2025 lax1dude. All Rights Reserved.
  * 
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
@@ -45,24 +40,17 @@ public class SkinServiceOffline implements ISkinService {
 
 	}
 
-	private final Map<UUID, CachedSkin> skinCache = new HashMap<>();
-
-	private final Multimap<UUID, UUID> onlinePlayersFromTexturesMap = MultimapBuilder.hashKeys().hashSetValues().build();
+	private final ConcurrentMap<UUID, CachedSkin> skinCache = new ConcurrentHashMap<>();
 
 	public void init(String uri, String driverClass, String driverPath, int keepObjectsDays, int keepProfilesDays,
 			int maxObjects, int maxProfiles) {
-		synchronized(skinCache) {
-			skinCache.clear();
-		}
+		skinCache.clear();
 	}
 
 	public void processGetOtherSkin(UUID searchUUID, UserConnection sender) {
 		EaglerInitialHandler initialHandler = (EaglerInitialHandler)sender.getPendingConnection();
 		if(initialHandler.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) {
-			CachedSkin cached;
-			synchronized(skinCache) {
-				cached = skinCache.get(searchUUID);
-			}
+			CachedSkin cached = skinCache.get(searchUUID);
 			if(cached != null) {
 				initialHandler.sendEaglerMessage(cached.packet.get(initialHandler.getEaglerProtocol()));
 			}else {
@@ -74,24 +62,6 @@ public class SkinServiceOffline implements ISkinService {
 
 	public void processGetOtherSkin(UUID searchUUID, String skinURL, UserConnection sender) {
 		EaglerInitialHandler initialHandler = (EaglerInitialHandler)sender.getPendingConnection();
-		Collection<UUID> uuids;
-		synchronized(onlinePlayersFromTexturesMap) {
-			uuids = onlinePlayersFromTexturesMap.get(searchUUID);
-		}
-		if(uuids.size() > 0) {
-			CachedSkin cached;
-			synchronized(skinCache) {
-				Iterator<UUID> uuidItr = uuids.iterator();
-				while(uuidItr.hasNext()) {
-					cached = skinCache.get(uuidItr.next());
-					if(cached != null) {
-						initialHandler.sendEaglerMessage(cached.packet.get(initialHandler.getEaglerProtocol(),
-								searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits()));
-						return;
-					}
-				}
-			}
-		}
 		if(skinURL.startsWith("eagler://")) { // customs skulls from exported singleplayer worlds
 			initialHandler.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(),
 					searchUUID.getLeastSignificantBits(), 0));
@@ -102,28 +72,21 @@ public class SkinServiceOffline implements ISkinService {
 	}
 
 	public void registerEaglercraftPlayer(UUID clientUUID, SkinPacketVersionCache generatedPacket, int modelId) {
-		synchronized(skinCache) {
-			skinCache.put(clientUUID, new CachedSkin(clientUUID, generatedPacket));
-		}
+		skinCache.put(clientUUID, new CachedSkin(clientUUID, generatedPacket));
 	}
 
 	public void unregisterPlayer(UUID clientUUID) {
-		synchronized(skinCache) {
-			skinCache.remove(clientUUID);
-		}
+		skinCache.remove(clientUUID);
+	}
+
+	public void registerTextureToPlayerAssociation(String textureURL, UUID playerUUID) {
 	}
 
 	public void registerTextureToPlayerAssociation(UUID textureUUID, UUID playerUUID) {
-		synchronized(onlinePlayersFromTexturesMap) {
-			onlinePlayersFromTexturesMap.put(textureUUID, playerUUID);
-		}
 	}
 
 	public void processForceSkin(UUID playerUUID, EaglerInitialHandler initialHandler) {
-		CachedSkin cached;
-		synchronized(skinCache) {
-			cached = skinCache.get(playerUUID);
-		}
+		CachedSkin cached = skinCache.get(playerUUID);
 		if(cached != null) {
 			initialHandler.sendEaglerMessage(cached.packet.getForceClientV4());
 		}
@@ -134,16 +97,11 @@ public class SkinServiceOffline implements ISkinService {
 	}
 
 	public void shutdown() {
-		synchronized(skinCache) {
-			skinCache.clear();
-		}
+		skinCache.clear();
 	}
 
 	public SkinPacketVersionCache getSkin(UUID playerUUID) {
-		CachedSkin cached;
-		synchronized(skinCache) {
-			cached = skinCache.get(playerUUID);
-		}
+		CachedSkin cached = skinCache.get(playerUUID);
 		return cached != null ? cached.packet : null;
 	}
 
diff --git a/gateway/EaglercraftXBungee/src/main/resources/plugin.yml b/gateway/EaglercraftXBungee/src/main/resources/plugin.yml
index 1b21af08..01d7794b 100644
--- a/gateway/EaglercraftXBungee/src/main/resources/plugin.yml
+++ b/gateway/EaglercraftXBungee/src/main/resources/plugin.yml
@@ -1,5 +1,5 @@
 name: EaglercraftXBungee
 main: net.lax1dude.eaglercraft.v1_8.plugin.gateway_bungeecord.EaglerXBungee
-version: 1.3.4
+version: 1.3.5
 description: Plugin to allow EaglercraftX 1.8 players to join your network, or allow EaglercraftX 1.8 players to use your network as a proxy to join other networks
 author: lax1dude
\ No newline at end of file
diff --git a/gateway_version b/gateway_version
index 8c9698aa..aaf8be71 100644
--- a/gateway_version
+++ b/gateway_version
@@ -1 +1 @@
-1.3.4
\ No newline at end of file
+1.3.5
\ No newline at end of file