mirror of
https://git.eaglercraft.rip/eaglercraft/eaglercraft-1.8.git
synced 2025-01-22 12:11:51 -05:00
<1.1.6> Reduce lock contention in EaglerXVelocity
This commit is contained in:
parent
1321b5d680
commit
3f5ee57068
12 changed files with 257 additions and 374 deletions
Binary file not shown.
|
@ -17,13 +17,14 @@ package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity;
|
||||||
*/
|
*/
|
||||||
public class EaglerXVelocityVersion {
|
public class EaglerXVelocityVersion {
|
||||||
|
|
||||||
public static final String NATIVE_VELOCITY_BUILD = "3.4.0-SNAPSHOT:a33f2d1a:b452";
|
public static final String NATIVE_VELOCITY_BUILD = "3.4.0-SNAPSHOT:71feb11b:b461";
|
||||||
|
public static final String NATIVE_VELOCITY_BUILD_DL = "https://api.papermc.io/v2/projects/velocity/versions/3.4.0-SNAPSHOT/builds/461/downloads/velocity-3.4.0-SNAPSHOT-461.jar";
|
||||||
|
|
||||||
public static final String ID = "EaglerXVelocity";
|
public static final String ID = "EaglerXVelocity";
|
||||||
public static final String PLUGIN_ID = "eaglerxvelocity";
|
public static final String PLUGIN_ID = "eaglerxvelocity";
|
||||||
public static final String NAME = "EaglercraftXVelocity";
|
public static final String NAME = "EaglercraftXVelocity";
|
||||||
public static final String 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";
|
public static final String 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";
|
||||||
public static final String VERSION = "1.1.5";
|
public static final String VERSION = "1.1.6";
|
||||||
public static final String[] AUTHORS = new String[] { "lax1dude", "ayunami2000" };
|
public static final String[] AUTHORS = new String[] { "lax1dude", "ayunami2000" };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
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_velocity.api.EaglerXVelocityAPIHelper;
|
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.api.EaglerXVelocityAPIHelper;
|
||||||
|
|
||||||
|
@ -44,6 +46,7 @@ public class AuthLoadingCache<K, V> {
|
||||||
boolean shouldEvict(K key, V value);
|
boolean shouldEvict(K key, V value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final ReadWriteLock cacheMapLock;
|
||||||
private final Map<K, CacheEntry<V>> cacheMap;
|
private final Map<K, CacheEntry<V>> cacheMap;
|
||||||
private final CacheLoader<K, V> provider;
|
private final CacheLoader<K, V> provider;
|
||||||
private final long cacheTTL;
|
private final long cacheTTL;
|
||||||
|
@ -51,6 +54,7 @@ public class AuthLoadingCache<K, V> {
|
||||||
private long cacheTimer;
|
private long cacheTimer;
|
||||||
|
|
||||||
public AuthLoadingCache(CacheLoader<K, V> provider, long cacheTTL) {
|
public AuthLoadingCache(CacheLoader<K, V> provider, long cacheTTL) {
|
||||||
|
this.cacheMapLock = new ReentrantReadWriteLock();
|
||||||
this.cacheMap = new HashMap<>();
|
this.cacheMap = new HashMap<>();
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
this.cacheTTL = cacheTTL;
|
this.cacheTTL = cacheTTL;
|
||||||
|
@ -58,13 +62,19 @@ public class AuthLoadingCache<K, V> {
|
||||||
|
|
||||||
public V get(K key) {
|
public V get(K key) {
|
||||||
CacheEntry<V> etr;
|
CacheEntry<V> etr;
|
||||||
synchronized(cacheMap) {
|
cacheMapLock.readLock().lock();
|
||||||
|
try {
|
||||||
etr = cacheMap.get(key);
|
etr = cacheMap.get(key);
|
||||||
|
}finally {
|
||||||
|
cacheMapLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
if(etr == null) {
|
if(etr == null) {
|
||||||
|
cacheMapLock.writeLock().lock();
|
||||||
V loaded = provider.load(key);
|
V loaded = provider.load(key);
|
||||||
synchronized(cacheMap) {
|
try {
|
||||||
cacheMap.put(key, new CacheEntry<>(loaded));
|
cacheMap.put(key, new CacheEntry<>(loaded));
|
||||||
|
}finally {
|
||||||
|
cacheMapLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
return loaded;
|
return loaded;
|
||||||
}else {
|
}else {
|
||||||
|
@ -74,13 +84,17 @@ public class AuthLoadingCache<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void evict(K key) {
|
public void evict(K key) {
|
||||||
synchronized(cacheMap) {
|
cacheMapLock.writeLock().lock();
|
||||||
|
try {
|
||||||
cacheMap.remove(key);
|
cacheMap.remove(key);
|
||||||
|
}finally {
|
||||||
|
cacheMapLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void evictAll(CacheVisitor<K, V> visitor) {
|
public void evictAll(CacheVisitor<K, V> visitor) {
|
||||||
synchronized(cacheMap) {
|
cacheMapLock.writeLock().lock();
|
||||||
|
try {
|
||||||
Iterator<Entry<K,CacheEntry<V>>> itr = cacheMap.entrySet().iterator();
|
Iterator<Entry<K,CacheEntry<V>>> itr = cacheMap.entrySet().iterator();
|
||||||
while(itr.hasNext()) {
|
while(itr.hasNext()) {
|
||||||
Entry<K,CacheEntry<V>> etr = itr.next();
|
Entry<K,CacheEntry<V>> etr = itr.next();
|
||||||
|
@ -88,6 +102,8 @@ public class AuthLoadingCache<K, V> {
|
||||||
itr.remove();
|
itr.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}finally {
|
||||||
|
cacheMapLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +111,8 @@ public class AuthLoadingCache<K, V> {
|
||||||
long millis = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
long millis = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
||||||
if(millis - cacheTimer > (cacheTTL / 2L)) {
|
if(millis - cacheTimer > (cacheTTL / 2L)) {
|
||||||
cacheTimer = millis;
|
cacheTimer = millis;
|
||||||
synchronized(cacheMap) {
|
cacheMapLock.writeLock().lock();
|
||||||
|
try {
|
||||||
Iterator<CacheEntry<V>> mapItr = cacheMap.values().iterator();
|
Iterator<CacheEntry<V>> mapItr = cacheMap.values().iterator();
|
||||||
while(mapItr.hasNext()) {
|
while(mapItr.hasNext()) {
|
||||||
CacheEntry<V> etr = mapItr.next();
|
CacheEntry<V> etr = mapItr.next();
|
||||||
|
@ -103,13 +120,18 @@ public class AuthLoadingCache<K, V> {
|
||||||
mapItr.remove();
|
mapItr.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}finally {
|
||||||
|
cacheMapLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flush() {
|
public void flush() {
|
||||||
synchronized(cacheMap) {
|
cacheMapLock.writeLock().lock();
|
||||||
|
try {
|
||||||
cacheMap.clear();
|
cacheMap.clear();
|
||||||
|
}finally {
|
||||||
|
cacheMapLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,7 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
private static final Method loginEventFiredMethod;
|
private static final Method loginEventFiredMethod;
|
||||||
private static final Constructor<ConnectedPlayer> stupid3Constructor;
|
private static final Constructor<ConnectedPlayer> stupid3Constructor;
|
||||||
private static final Constructor<ConnectedPlayer> stupid3Constructor_new;
|
private static final Constructor<ConnectedPlayer> stupid3Constructor_new;
|
||||||
|
private static final Constructor<ConnectedPlayer> stupid3Constructor_new_new;
|
||||||
private static final Method setPermissionFunctionMethod;
|
private static final Method setPermissionFunctionMethod;
|
||||||
private static final Field defaultPermissionsField;
|
private static final Field defaultPermissionsField;
|
||||||
private static final Constructor<InitialConnectSessionHandler> stupid4Constructor;
|
private static final Constructor<InitialConnectSessionHandler> stupid4Constructor;
|
||||||
|
@ -137,16 +138,24 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
loginEventFiredMethod.setAccessible(true);
|
loginEventFiredMethod.setAccessible(true);
|
||||||
Constructor<ConnectedPlayer> c3 = null;
|
Constructor<ConnectedPlayer> c3 = null;
|
||||||
Constructor<ConnectedPlayer> c3_new = null;
|
Constructor<ConnectedPlayer> c3_new = null;
|
||||||
|
Constructor<ConnectedPlayer> c3_new_new = null;
|
||||||
try {
|
try {
|
||||||
|
c3_new_new = ConnectedPlayer.class.getDeclaredConstructor(VelocityServer.class, GameProfile.class, MinecraftConnection.class, InetSocketAddress.class, String.class, boolean.class, HandshakeIntent.class, IdentifiedKey.class);
|
||||||
|
c3_new_new.setAccessible(true);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
try {
|
||||||
|
c3_new_new = null;
|
||||||
c3_new = ConnectedPlayer.class.getDeclaredConstructor(VelocityServer.class, GameProfile.class, MinecraftConnection.class, InetSocketAddress.class, String.class, boolean.class, IdentifiedKey.class);
|
c3_new = ConnectedPlayer.class.getDeclaredConstructor(VelocityServer.class, GameProfile.class, MinecraftConnection.class, InetSocketAddress.class, String.class, boolean.class, IdentifiedKey.class);
|
||||||
c3_new.setAccessible(true);
|
c3_new.setAccessible(true);
|
||||||
} catch (NoSuchMethodException e) {
|
} catch (NoSuchMethodException ee) {
|
||||||
|
c3_new = null;
|
||||||
c3 = ConnectedPlayer.class.getDeclaredConstructor(VelocityServer.class, GameProfile.class, MinecraftConnection.class, InetSocketAddress.class, boolean.class, IdentifiedKey.class);
|
c3 = ConnectedPlayer.class.getDeclaredConstructor(VelocityServer.class, GameProfile.class, MinecraftConnection.class, InetSocketAddress.class, boolean.class, IdentifiedKey.class);
|
||||||
c3.setAccessible(true);
|
c3.setAccessible(true);
|
||||||
c3_new = null;
|
}
|
||||||
}
|
}
|
||||||
stupid3Constructor = c3;
|
stupid3Constructor = c3;
|
||||||
stupid3Constructor_new = c3_new;
|
stupid3Constructor_new = c3_new;
|
||||||
|
stupid3Constructor_new_new = c3_new_new;
|
||||||
setPermissionFunctionMethod = ConnectedPlayer.class.getDeclaredMethod("setPermissionFunction", PermissionFunction.class);
|
setPermissionFunctionMethod = ConnectedPlayer.class.getDeclaredMethod("setPermissionFunction", PermissionFunction.class);
|
||||||
setPermissionFunctionMethod.setAccessible(true);
|
setPermissionFunctionMethod.setAccessible(true);
|
||||||
defaultPermissionsField = ConnectedPlayer.class.getDeclaredField("DEFAULT_PERMISSIONS");
|
defaultPermissionsField = ConnectedPlayer.class.getDeclaredField("DEFAULT_PERMISSIONS");
|
||||||
|
@ -1080,7 +1089,13 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectedPlayer player;
|
ConnectedPlayer player;
|
||||||
if(stupid3Constructor_new != null) {
|
if(stupid3Constructor_new_new != null) {
|
||||||
|
try {
|
||||||
|
player = stupid3Constructor_new_new.newInstance(bungee, gp, con, lic.getVirtualHost().orElse(null), lic.getRawVirtualHost().orElse(null), false, HandshakeIntent.LOGIN, lic.getIdentifiedKey());
|
||||||
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}else if(stupid3Constructor_new != null) {
|
||||||
try {
|
try {
|
||||||
player = stupid3Constructor_new.newInstance(bungee, gp, con, lic.getVirtualHost().orElse(null), lic.getRawVirtualHost().orElse(null), false, lic.getIdentifiedKey());
|
player = stupid3Constructor_new.newInstance(bungee, gp, con, lic.getVirtualHost().orElse(null), lic.getRawVirtualHost().orElse(null), false, lic.getIdentifiedKey());
|
||||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||||
|
@ -1309,14 +1324,11 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
pp.remove(HttpWebSocketHandler.this);
|
pp.remove(HttpWebSocketHandler.this);
|
||||||
|
|
||||||
pp
|
pp.addLast("EaglerMinecraftByteBufDecoder", new EaglerMinecraftDecoder())
|
||||||
.addLast("EaglerMinecraftByteBufDecoder", new EaglerMinecraftDecoder())
|
|
||||||
.addLast(LEGACY_PING_DECODER, new LegacyPingDecoder())
|
|
||||||
.addLast(READ_TIMEOUT,
|
.addLast(READ_TIMEOUT,
|
||||||
new ReadTimeoutHandler(bungee.getConfiguration().getReadTimeout(),
|
new ReadTimeoutHandler(bungee.getConfiguration().getReadTimeout(),
|
||||||
TimeUnit.MILLISECONDS))
|
TimeUnit.MILLISECONDS))
|
||||||
.addLast("EaglerMinecraftByteBufEncoder", new EaglerMinecraftEncoder())
|
.addLast("EaglerMinecraftByteBufEncoder", new EaglerMinecraftEncoder())
|
||||||
.addLast(LEGACY_PING_ENCODER, LegacyPingEncoder.INSTANCE)
|
|
||||||
.addLast(MINECRAFT_DECODER, new MinecraftDecoder(ProtocolUtils.Direction.SERVERBOUND))
|
.addLast(MINECRAFT_DECODER, new MinecraftDecoder(ProtocolUtils.Direction.SERVERBOUND))
|
||||||
.addLast(MINECRAFT_ENCODER, new MinecraftEncoder(ProtocolUtils.Direction.CLIENTBOUND));
|
.addLast(MINECRAFT_ENCODER, new MinecraftEncoder(ProtocolUtils.Direction.CLIENTBOUND));
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.protocol;
|
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.protocol;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
@ -241,10 +242,12 @@ public class GameProtocolMessageController {
|
||||||
while(!sendQueueV4.isEmpty()) {
|
while(!sendQueueV4.isEmpty()) {
|
||||||
sendCount = 0;
|
sendCount = 0;
|
||||||
totalLen = 0;
|
totalLen = 0;
|
||||||
|
Iterator<byte[]> itr = sendQueueV4.iterator();
|
||||||
do {
|
do {
|
||||||
i = sendQueueV4.get(sendCount++).length;
|
i = itr.next().length;
|
||||||
totalLen += GamePacketOutputBuffer.getVarIntSize(i) + i;
|
totalLen += GamePacketOutputBuffer.getVarIntSize(i) + i;
|
||||||
}while(totalLen < 32760 && sendCount < sendQueueV4.size());
|
++sendCount;
|
||||||
|
}while(totalLen < 32760 && itr.hasNext());
|
||||||
if(totalLen >= 32760) {
|
if(totalLen >= 32760) {
|
||||||
--sendCount;
|
--sendCount;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,6 @@ public class HttpWebServer {
|
||||||
private final String page404;
|
private final String page404;
|
||||||
private static HttpMemoryCache default404Page;
|
private static HttpMemoryCache default404Page;
|
||||||
private static HttpMemoryCache default404UpgradePage;
|
private static HttpMemoryCache default404UpgradePage;
|
||||||
private static final Object cacheClearLock = new Object();
|
|
||||||
|
|
||||||
public HttpWebServer(File directory, Map<String,HttpContentType> contentTypes, List<String> index, String page404) {
|
public HttpWebServer(File directory, Map<String,HttpContentType> contentTypes, List<String> index, String page404) {
|
||||||
this.directory = directory;
|
this.directory = directory;
|
||||||
|
@ -53,7 +52,6 @@ public class HttpWebServer {
|
||||||
|
|
||||||
public void flushCache() {
|
public void flushCache() {
|
||||||
long millis = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
long millis = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
||||||
synchronized(cacheClearLock) {
|
|
||||||
synchronized(filesCache) {
|
synchronized(filesCache) {
|
||||||
Iterator<HttpMemoryCache> itr = filesCache.values().iterator();
|
Iterator<HttpMemoryCache> itr = filesCache.values().iterator();
|
||||||
while(itr.hasNext()) {
|
while(itr.hasNext()) {
|
||||||
|
@ -65,7 +63,6 @@ public class HttpWebServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public HttpMemoryCache retrieveFile(String path) {
|
public HttpMemoryCache retrieveFile(String path) {
|
||||||
try {
|
try {
|
||||||
|
@ -95,21 +92,18 @@ public class HttpWebServer {
|
||||||
|
|
||||||
String joinedPath = String.join("/", pathList);
|
String joinedPath = String.join("/", pathList);
|
||||||
|
|
||||||
synchronized(cacheClearLock) {
|
//TODO: Rewrite this to cause less lock contention
|
||||||
synchronized(filesCache) {
|
synchronized(filesCache) {
|
||||||
cached = filesCache.get(joinedPath);
|
cached = filesCache.get(joinedPath);
|
||||||
}
|
|
||||||
|
|
||||||
if(cached != null) {
|
if(cached != null) {
|
||||||
cached = validateCache(cached);
|
cached = validateCache(cached);
|
||||||
if(cached != null) {
|
if(cached != null) {
|
||||||
return cached;
|
return cached;
|
||||||
}else {
|
}else {
|
||||||
synchronized(filesCache) {
|
|
||||||
filesCache.remove(joinedPath);
|
filesCache.remove(joinedPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
File f = new File(directory, joinedPath);
|
File f = new File(directory, joinedPath);
|
||||||
|
|
||||||
|
@ -124,19 +118,13 @@ public class HttpWebServer {
|
||||||
if(f.isDirectory()) {
|
if(f.isDirectory()) {
|
||||||
for(int i = 0, l = index.size(); i < l; ++i) {
|
for(int i = 0, l = index.size(); i < l; ++i) {
|
||||||
String p = joinedPath + "/" + index.get(i);
|
String p = joinedPath + "/" + index.get(i);
|
||||||
synchronized(filesCache) {
|
|
||||||
cached = filesCache.get(p);
|
cached = filesCache.get(p);
|
||||||
}
|
|
||||||
if(cached != null) {
|
if(cached != null) {
|
||||||
cached = validateCache(cached);
|
cached = validateCache(cached);
|
||||||
if(cached != null) {
|
if(cached != null) {
|
||||||
synchronized(filesCache) {
|
|
||||||
filesCache.put(joinedPath, cached);
|
filesCache.put(joinedPath, cached);
|
||||||
}
|
|
||||||
}else {
|
}else {
|
||||||
synchronized(filesCache) {
|
|
||||||
filesCache.remove(p);
|
filesCache.remove(p);
|
||||||
}
|
|
||||||
if(page404 == null || path.equals(page404)) {
|
if(page404 == null || path.equals(page404)) {
|
||||||
return default404Page;
|
return default404Page;
|
||||||
}else {
|
}else {
|
||||||
|
@ -152,9 +140,7 @@ public class HttpWebServer {
|
||||||
if(ff.isFile()) {
|
if(ff.isFile()) {
|
||||||
HttpMemoryCache memCache = retrieveFile(ff, p);
|
HttpMemoryCache memCache = retrieveFile(ff, p);
|
||||||
if(memCache != null) {
|
if(memCache != null) {
|
||||||
synchronized(filesCache) {
|
|
||||||
filesCache.put(joinedPath, memCache);
|
filesCache.put(joinedPath, memCache);
|
||||||
}
|
|
||||||
return memCache;
|
return memCache;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,9 +153,7 @@ public class HttpWebServer {
|
||||||
}else {
|
}else {
|
||||||
HttpMemoryCache memCache = retrieveFile(f, joinedPath);
|
HttpMemoryCache memCache = retrieveFile(f, joinedPath);
|
||||||
if(memCache != null) {
|
if(memCache != null) {
|
||||||
synchronized(filesCache) {
|
|
||||||
filesCache.put(joinedPath, memCache);
|
filesCache.put(joinedPath, memCache);
|
||||||
}
|
|
||||||
return memCache;
|
return memCache;
|
||||||
}else {
|
}else {
|
||||||
if(page404 == null || path.equals(page404)) {
|
if(page404 == null || path.equals(page404)) {
|
||||||
|
|
|
@ -34,6 +34,7 @@ public class CompatWarning {
|
||||||
":> apart from the versions listed below:",
|
":> apart from the versions listed below:",
|
||||||
":> ",
|
":> ",
|
||||||
":> - Velocity: " + EaglerXVelocityVersion.NATIVE_VELOCITY_BUILD,
|
":> - Velocity: " + EaglerXVelocityVersion.NATIVE_VELOCITY_BUILD,
|
||||||
|
":> - " + EaglerXVelocityVersion.NATIVE_VELOCITY_BUILD_DL,
|
||||||
":> ",
|
":> ",
|
||||||
":> This is not a Bukkit/Spigot plugin!",
|
":> This is not a Bukkit/Spigot plugin!",
|
||||||
":> ",
|
":> ",
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins;
|
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData;
|
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData;
|
||||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket;
|
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket;
|
||||||
|
@ -12,7 +12,7 @@ import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCape
|
||||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCapePresetEAG;
|
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherCapePresetEAG;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
* 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
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
@ -30,20 +30,15 @@ public class CapeServiceOffline {
|
||||||
|
|
||||||
public static final int masterRateLimitPerPlayer = 250;
|
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) {
|
public void registerEaglercraftPlayer(UUID playerUUID, GameMessagePacket capePacket) {
|
||||||
synchronized(capesCache) {
|
|
||||||
capesCache.put(playerUUID, capePacket);
|
capesCache.put(playerUUID, capePacket);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void processGetOtherCape(UUID searchUUID, EaglerPlayerData sender) {
|
public void processGetOtherCape(UUID searchUUID, EaglerPlayerData sender) {
|
||||||
if(sender.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) {
|
if(sender.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) {
|
||||||
GameMessagePacket maybeCape;
|
GameMessagePacket maybeCape = capesCache.get(searchUUID);
|
||||||
synchronized(capesCache) {
|
|
||||||
maybeCape = capesCache.get(searchUUID);
|
|
||||||
}
|
|
||||||
if(maybeCape != null) {
|
if(maybeCape != null) {
|
||||||
sender.sendEaglerMessage(maybeCape);
|
sender.sendEaglerMessage(maybeCape);
|
||||||
}else {
|
}else {
|
||||||
|
@ -54,10 +49,7 @@ public class CapeServiceOffline {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processForceCape(UUID clientUUID, EaglerPlayerData initialHandler) {
|
public void processForceCape(UUID clientUUID, EaglerPlayerData initialHandler) {
|
||||||
GameMessagePacket maybeCape;
|
GameMessagePacket maybeCape = capesCache.get(clientUUID);
|
||||||
synchronized(capesCache) {
|
|
||||||
maybeCape = capesCache.get(clientUUID);
|
|
||||||
}
|
|
||||||
if(maybeCape != null) {
|
if(maybeCape != null) {
|
||||||
if (maybeCape instanceof SPacketOtherCapePresetEAG) {
|
if (maybeCape instanceof SPacketOtherCapePresetEAG) {
|
||||||
initialHandler.sendEaglerMessage(
|
initialHandler.sendEaglerMessage(
|
||||||
|
@ -70,16 +62,12 @@ public class CapeServiceOffline {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unregisterPlayer(UUID playerUUID) {
|
public void unregisterPlayer(UUID playerUUID) {
|
||||||
synchronized(capesCache) {
|
|
||||||
capesCache.remove(playerUUID);
|
capesCache.remove(playerUUID);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public GameMessagePacket getCape(UUID clientUUID) {
|
public GameMessagePacket getCape(UUID clientUUID) {
|
||||||
synchronized(capesCache) {
|
|
||||||
return capesCache.get(clientUUID);
|
return capesCache.get(clientUUID);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getCapeHandshakeData(UUID clientUUID) {
|
public byte[] getCapeHandshakeData(UUID clientUUID) {
|
||||||
GameMessagePacket capePacket = getCape(clientUUID);
|
GameMessagePacket capePacket = getCape(clientUUID);
|
||||||
|
@ -107,8 +95,6 @@ public class CapeServiceOffline {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
synchronized(capesCache) {
|
|
||||||
capesCache.clear();
|
capesCache.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins;
|
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -10,6 +11,10 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
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 java.util.function.Consumer;
|
||||||
|
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
@ -36,7 +41,7 @@ import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkin
|
||||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache;
|
import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
* 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
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
@ -54,16 +59,20 @@ public class SkinService implements ISkinService {
|
||||||
|
|
||||||
public static final int masterRateLimitPerPlayer = 250;
|
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 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, PendingTextureDownload> pendingTextures = new HashMap<>();
|
||||||
private final Map<UUID, PendingProfileUUIDLookup> pendingUUIDs = new HashMap<>();
|
private final Map<UUID, PendingProfileUUIDLookup> pendingUUIDs = new HashMap<>();
|
||||||
private final Map<String, PendingProfileNameLookup> pendingNameLookups = new HashMap<>();
|
private final Map<String, PendingProfileNameLookup> pendingNameLookups = new HashMap<>();
|
||||||
|
|
||||||
|
private final ReadWriteLock antagonistsLock = new ReentrantReadWriteLock();
|
||||||
private final Object2IntMap<UUID> antagonists = new Object2IntOpenHashMap<>();
|
private final Object2IntMap<UUID> antagonists = new Object2IntOpenHashMap<>();
|
||||||
|
|
||||||
private long antagonistCooldown = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
private long antagonistCooldown = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
||||||
|
|
||||||
private final Consumer<Set<UUID>> antagonistLogger = new Consumer<Set<UUID>>() {
|
private final Consumer<Set<UUID>> antagonistLogger = new Consumer<Set<UUID>>() {
|
||||||
|
@ -73,7 +82,8 @@ public class SkinService implements ISkinService {
|
||||||
if(t.size() == 1) {
|
if(t.size() == 1) {
|
||||||
int limit = EaglerXVelocity.getEagler().getConfig().getAntagonistsRateLimit() << 1;
|
int limit = EaglerXVelocity.getEagler().getConfig().getAntagonistsRateLimit() << 1;
|
||||||
UUID offender = t.iterator().next();
|
UUID offender = t.iterator().next();
|
||||||
synchronized(antagonists) {
|
antagonistsLock.writeLock().lock();
|
||||||
|
try {
|
||||||
int v = antagonists.getInt(offender);
|
int v = antagonists.getInt(offender);
|
||||||
if(v == antagonists.defaultReturnValue()) {
|
if(v == antagonists.defaultReturnValue()) {
|
||||||
antagonists.put(offender, 1);
|
antagonists.put(offender, 1);
|
||||||
|
@ -82,6 +92,8 @@ public class SkinService implements ISkinService {
|
||||||
antagonists.put(offender, v + 1);
|
antagonists.put(offender, v + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}finally {
|
||||||
|
antagonistsLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +107,7 @@ public class SkinService implements ISkinService {
|
||||||
protected final UUID uuid;
|
protected final UUID uuid;
|
||||||
protected final SkinPacketVersionCache data;
|
protected final SkinPacketVersionCache data;
|
||||||
protected final int modelKnown;
|
protected final int modelKnown;
|
||||||
protected long lastHit;
|
protected volatile long lastHit;
|
||||||
|
|
||||||
protected CachedForeignSkin(UUID uuid, SkinPacketVersionCache data, int modelKnown) {
|
protected CachedForeignSkin(UUID uuid, SkinPacketVersionCache data, int modelKnown) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
|
@ -130,7 +142,7 @@ public class SkinService implements ISkinService {
|
||||||
protected final Consumer<Set<UUID>> antagonistsCallback;
|
protected final Consumer<Set<UUID>> antagonistsCallback;
|
||||||
|
|
||||||
protected final long initializedTime;
|
protected final long initializedTime;
|
||||||
protected boolean finalized;
|
protected volatile boolean finalized;
|
||||||
|
|
||||||
protected PendingTextureDownload(UUID textureUUID, String textureURL, UUID caller, Consumer<byte[]> callback,
|
protected PendingTextureDownload(UUID textureUUID, String textureURL, UUID caller, Consumer<byte[]> callback,
|
||||||
Consumer<Set<UUID>> antagonistsCallback) {
|
Consumer<Set<UUID>> antagonistsCallback) {
|
||||||
|
@ -172,7 +184,7 @@ public class SkinService implements ISkinService {
|
||||||
protected final Consumer<Set<UUID>> antagonistsCallback;
|
protected final Consumer<Set<UUID>> antagonistsCallback;
|
||||||
|
|
||||||
protected final long initializedTime;
|
protected final long initializedTime;
|
||||||
protected boolean finalized;
|
protected volatile boolean finalized;
|
||||||
|
|
||||||
protected PendingProfileUUIDLookup(UUID profileUUID, UUID caller, Consumer<CacheFetchedProfile> callback,
|
protected PendingProfileUUIDLookup(UUID profileUUID, UUID caller, Consumer<CacheFetchedProfile> callback,
|
||||||
Consumer<Set<UUID>> antagonistsCallback) {
|
Consumer<Set<UUID>> antagonistsCallback) {
|
||||||
|
@ -213,7 +225,7 @@ public class SkinService implements ISkinService {
|
||||||
protected final Consumer<Set<UUID>> antagonistsCallback;
|
protected final Consumer<Set<UUID>> antagonistsCallback;
|
||||||
|
|
||||||
protected final long initializedTime;
|
protected final long initializedTime;
|
||||||
protected boolean finalized;
|
protected volatile boolean finalized;
|
||||||
|
|
||||||
protected PendingProfileNameLookup(String profileName, UUID caller, Consumer<CacheFetchedProfile> callback,
|
protected PendingProfileNameLookup(String profileName, UUID caller, Consumer<CacheFetchedProfile> callback,
|
||||||
Consumer<Set<UUID>> antagonistsCallback) {
|
Consumer<Set<UUID>> antagonistsCallback) {
|
||||||
|
@ -260,60 +272,46 @@ public class SkinService implements ISkinService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedPlayerSkin maybeCachedPacket;
|
CachedPlayerSkin maybeCachedPacket = onlinePlayersCache.get(searchUUID);
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
maybeCachedPacket = onlinePlayersCache.get(searchUUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(maybeCachedPacket != null) {
|
if(maybeCachedPacket != null) {
|
||||||
sender.sendEaglerMessage(maybeCachedPacket.data.get(sender.getEaglerProtocol()));
|
sender.sendEaglerMessage(maybeCachedPacket.data.get(sender.getEaglerProtocol()));
|
||||||
}else {
|
}else {
|
||||||
Player player = EaglerXVelocity.proxy().getPlayer(searchUUID).orElse(null);
|
Player player = EaglerXVelocity.proxy().getPlayer(searchUUID).orElse(null);
|
||||||
UUID playerTexture;
|
UUID playerTexture = onlinePlayersToTexturesMap.get(searchUUID);
|
||||||
synchronized(onlinePlayersToTexturesMap) {
|
|
||||||
playerTexture = onlinePlayersToTexturesMap.get(searchUUID);
|
|
||||||
}
|
|
||||||
if(playerTexture != null) {
|
if(playerTexture != null) {
|
||||||
Collection<UUID> possiblePlayers;
|
Collection<UUID> possiblePlayers;
|
||||||
synchronized(onlinePlayersFromTexturesMap) {
|
onlinePlayersFromTexturesMapLock.readLock().lock();
|
||||||
possiblePlayers = onlinePlayersFromTexturesMap.get(playerTexture);
|
try {
|
||||||
|
possiblePlayers = new ArrayList<>(onlinePlayersFromTexturesMap.get(playerTexture));
|
||||||
|
}finally {
|
||||||
|
onlinePlayersFromTexturesMapLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
boolean playersExist = possiblePlayers.size() > 0;
|
boolean playersExist = possiblePlayers.size() > 0;
|
||||||
if(playersExist) {
|
if(playersExist) {
|
||||||
for(UUID uuid : possiblePlayers) {
|
for(UUID uuid : possiblePlayers) {
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
maybeCachedPacket = onlinePlayersCache.get(uuid);
|
maybeCachedPacket = onlinePlayersCache.get(uuid);
|
||||||
}
|
|
||||||
if(maybeCachedPacket != null) {
|
if(maybeCachedPacket != null) {
|
||||||
SkinPacketVersionCache rewritten = SkinPacketVersionCache.rewriteUUID(
|
SkinPacketVersionCache rewritten = SkinPacketVersionCache.rewriteUUID(
|
||||||
maybeCachedPacket.data, searchUUID.getMostSignificantBits(),
|
maybeCachedPacket.data, searchUUID.getMostSignificantBits(),
|
||||||
searchUUID.getLeastSignificantBits());
|
searchUUID.getLeastSignificantBits());
|
||||||
if(player != null) {
|
if(player != null) {
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
onlinePlayersCache.put(searchUUID, new CachedPlayerSkin(rewritten,
|
onlinePlayersCache.put(searchUUID, new CachedPlayerSkin(rewritten,
|
||||||
maybeCachedPacket.textureUUID, maybeCachedPacket.modelId));
|
maybeCachedPacket.textureUUID, maybeCachedPacket.modelId));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
sender.sendEaglerMessage(rewritten.get(sender.getEaglerProtocol()));
|
sender.sendEaglerMessage(rewritten.get(sender.getEaglerProtocol()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CachedForeignSkin foreignSkin;
|
CachedForeignSkin foreignSkin = foreignSkinCache.get(playerTexture);
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
foreignSkin = foreignSkinCache.get(playerTexture);
|
|
||||||
}
|
|
||||||
if(foreignSkin != null && foreignSkin.modelKnown != -1) {
|
if(foreignSkin != null && foreignSkin.modelKnown != -1) {
|
||||||
if(player != null) {
|
if(player != null) {
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
onlinePlayersCache.put(searchUUID,
|
onlinePlayersCache.put(searchUUID,
|
||||||
new CachedPlayerSkin(SkinPacketVersionCache.rewriteUUID(foreignSkin.data,
|
new CachedPlayerSkin(SkinPacketVersionCache.rewriteUUID(foreignSkin.data,
|
||||||
searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits()),
|
searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits()),
|
||||||
playerTexture, foreignSkin.modelKnown));
|
playerTexture, foreignSkin.modelKnown));
|
||||||
}
|
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
foreignSkinCache.remove(playerTexture);
|
foreignSkinCache.remove(playerTexture);
|
||||||
}
|
|
||||||
}else {
|
}else {
|
||||||
foreignSkin.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
foreignSkin.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
||||||
}
|
}
|
||||||
|
@ -336,7 +334,7 @@ public class SkinService implements ISkinService {
|
||||||
if(skinObj != null) {
|
if(skinObj != null) {
|
||||||
JsonElement url = json.get("url");
|
JsonElement url = json.get("url");
|
||||||
if(url != null) {
|
if(url != null) {
|
||||||
String urlStr = SkinService.sanitizeTextureURL(url.getAsString());
|
String urlStr = sanitizeTextureURL(url.getAsString());
|
||||||
if(urlStr == null) {
|
if(urlStr == null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -350,19 +348,14 @@ public class SkinService implements ISkinService {
|
||||||
}
|
}
|
||||||
UUID skinUUID = SkinPackets.createEaglerURLSkinUUID(urlStr);
|
UUID skinUUID = SkinPackets.createEaglerURLSkinUUID(urlStr);
|
||||||
|
|
||||||
CachedForeignSkin foreignSkin;
|
CachedForeignSkin foreignSkin = foreignSkinCache.remove(skinUUID);
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
foreignSkin = foreignSkinCache.remove(skinUUID);
|
|
||||||
}
|
|
||||||
if(foreignSkin != null) {
|
if(foreignSkin != null) {
|
||||||
registerTextureToPlayerAssociation(skinUUID, searchUUID);
|
registerTextureToPlayerAssociation(skinUUID, searchUUID);
|
||||||
SkinPacketVersionCache rewrite = SkinPacketVersionCache
|
SkinPacketVersionCache rewrite = SkinPacketVersionCache
|
||||||
.rewriteUUIDModel(foreignSkin.data,
|
.rewriteUUIDModel(foreignSkin.data,
|
||||||
searchUUID.getMostSignificantBits(),
|
searchUUID.getMostSignificantBits(),
|
||||||
searchUUID.getLeastSignificantBits(), model);
|
searchUUID.getLeastSignificantBits(), model);
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
onlinePlayersCache.put(searchUUID, new CachedPlayerSkin(rewrite, skinUUID, model));
|
onlinePlayersCache.put(searchUUID, new CachedPlayerSkin(rewrite, skinUUID, model));
|
||||||
}
|
|
||||||
sender.sendEaglerMessage(rewrite.get(sender.getEaglerProtocol()));
|
sender.sendEaglerMessage(rewrite.get(sender.getEaglerProtocol()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -395,10 +388,7 @@ public class SkinService implements ISkinService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
CachedForeignSkin foreignSkin;
|
CachedForeignSkin foreignSkin = foreignSkinCache.get(searchUUID);
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
foreignSkin = foreignSkinCache.get(searchUUID);
|
|
||||||
}
|
|
||||||
if(foreignSkin != null) {
|
if(foreignSkin != null) {
|
||||||
foreignSkin.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
foreignSkin.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
||||||
sender.sendEaglerMessage(foreignSkin.data.get(sender.getEaglerProtocol()));
|
sender.sendEaglerMessage(foreignSkin.data.get(sender.getEaglerProtocol()));
|
||||||
|
@ -426,25 +416,22 @@ public class SkinService implements ISkinService {
|
||||||
if(!sender.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) {
|
if(!sender.skinLookupRateLimiter.rateLimit(masterRateLimitPerPlayer)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CachedForeignSkin foreignSkin;
|
CachedForeignSkin foreignSkin = foreignSkinCache.get(searchUUID);
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
foreignSkin = foreignSkinCache.get(searchUUID);
|
|
||||||
}
|
|
||||||
if(foreignSkin != null) {
|
if(foreignSkin != null) {
|
||||||
foreignSkin.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
foreignSkin.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
||||||
sender.sendEaglerMessage(foreignSkin.data.get(sender.getEaglerProtocol()));
|
sender.sendEaglerMessage(foreignSkin.data.get(sender.getEaglerProtocol()));
|
||||||
}else {
|
}else {
|
||||||
Collection<UUID> possiblePlayers;
|
Collection<UUID> possiblePlayers;
|
||||||
synchronized(onlinePlayersFromTexturesMap) {
|
onlinePlayersFromTexturesMapLock.readLock().lock();
|
||||||
possiblePlayers = onlinePlayersFromTexturesMap.get(searchUUID);
|
try {
|
||||||
|
possiblePlayers = new ArrayList<>(onlinePlayersFromTexturesMap.get(searchUUID));
|
||||||
|
}finally {
|
||||||
|
onlinePlayersFromTexturesMapLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
boolean playersExist = possiblePlayers.size() > 0;
|
boolean playersExist = possiblePlayers.size() > 0;
|
||||||
if(playersExist) {
|
if(playersExist) {
|
||||||
for(UUID uuid : possiblePlayers) {
|
for(UUID uuid : possiblePlayers) {
|
||||||
CachedPlayerSkin maybeCachedPacket;
|
CachedPlayerSkin maybeCachedPacket = onlinePlayersCache.get(uuid);
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
maybeCachedPacket = onlinePlayersCache.get(uuid);
|
|
||||||
}
|
|
||||||
if(maybeCachedPacket != null) {
|
if(maybeCachedPacket != null) {
|
||||||
sender.sendEaglerMessage(maybeCachedPacket.data.get(sender.getEaglerProtocol(),
|
sender.sendEaglerMessage(maybeCachedPacket.data.get(sender.getEaglerProtocol(),
|
||||||
searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits()));
|
searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits()));
|
||||||
|
@ -457,11 +444,18 @@ public class SkinService implements ISkinService {
|
||||||
searchUUID.getLeastSignificantBits(), 0));
|
searchUUID.getLeastSignificantBits(), 0));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
skinURL = sanitizeTextureURL(skinURL);
|
||||||
|
if(skinURL != null) {
|
||||||
|
final String skinURL_ = skinURL;
|
||||||
if(sender.skinTextureDownloadRateLimiter.rateLimit(config.getSkinRateLimitPlayer()) && !isLimitedAsAntagonist(sender.getUniqueId())) {
|
if(sender.skinTextureDownloadRateLimiter.rateLimit(config.getSkinRateLimitPlayer()) && !isLimitedAsAntagonist(sender.getUniqueId())) {
|
||||||
doAsync(() -> {
|
doAsync(() -> {
|
||||||
processResolveURLTextureForForeign(sender, searchUUID, searchUUID, skinURL, -1);
|
processResolveURLTextureForForeign(sender, searchUUID, searchUUID, skinURL_, -1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}else {
|
||||||
|
sender.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(),
|
||||||
|
searchUUID.getLeastSignificantBits(), 0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,10 +469,7 @@ public class SkinService implements ISkinService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(byte[] t) {
|
public void accept(byte[] t) {
|
||||||
CachedPlayerSkin skin;
|
CachedPlayerSkin skin = onlinePlayersCache.get(onlineCacheUUID);
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
skin = onlinePlayersCache.get(onlineCacheUUID);
|
|
||||||
}
|
|
||||||
if(skin != null) {
|
if(skin != null) {
|
||||||
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
||||||
}
|
}
|
||||||
|
@ -505,9 +496,7 @@ public class SkinService implements ISkinService {
|
||||||
onlineCacheUUID.getMostSignificantBits(),
|
onlineCacheUUID.getMostSignificantBits(),
|
||||||
onlineCacheUUID.getLeastSignificantBits()), null, -1);
|
onlineCacheUUID.getLeastSignificantBits()), null, -1);
|
||||||
}
|
}
|
||||||
synchronized (onlinePlayersCache) {
|
|
||||||
onlinePlayersCache.put(onlineCacheUUID, skin);
|
onlinePlayersCache.put(onlineCacheUUID, skin);
|
||||||
}
|
|
||||||
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,10 +521,7 @@ public class SkinService implements ISkinService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(byte[] t) {
|
public void accept(byte[] t) {
|
||||||
CachedForeignSkin skin;
|
CachedForeignSkin skin = foreignSkinCache.get(foreignCacheUUID);
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
skin = foreignSkinCache.get(foreignCacheUUID);
|
|
||||||
}
|
|
||||||
if(skin != null) {
|
if(skin != null) {
|
||||||
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
||||||
}
|
}
|
||||||
|
@ -563,9 +549,7 @@ public class SkinService implements ISkinService {
|
||||||
foreignCacheUUID.getLeastSignificantBits()),
|
foreignCacheUUID.getLeastSignificantBits()),
|
||||||
-1);
|
-1);
|
||||||
}
|
}
|
||||||
synchronized (foreignSkinCache) {
|
|
||||||
foreignSkinCache.put(foreignCacheUUID, skin);
|
foreignSkinCache.put(foreignCacheUUID, skin);
|
||||||
}
|
|
||||||
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,10 +574,7 @@ public class SkinService implements ISkinService {
|
||||||
@Override
|
@Override
|
||||||
public void accept(CacheFetchedProfile t) {
|
public void accept(CacheFetchedProfile t) {
|
||||||
if(t == null || t.texture == null) {
|
if(t == null || t.texture == null) {
|
||||||
CachedPlayerSkin skin;
|
CachedPlayerSkin skin = onlinePlayersCache.get(playerUUID);
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
skin = onlinePlayersCache.get(playerUUID);
|
|
||||||
}
|
|
||||||
if(skin != null) {
|
if(skin != null) {
|
||||||
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
||||||
}
|
}
|
||||||
|
@ -625,9 +606,7 @@ public class SkinService implements ISkinService {
|
||||||
SkinPackets.getModelId(t.model) == 1 ? 1 : 0),
|
SkinPackets.getModelId(t.model) == 1 ? 1 : 0),
|
||||||
null, -1);
|
null, -1);
|
||||||
}
|
}
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
onlinePlayersCache.put(playerUUID, skin);
|
onlinePlayersCache.put(playerUUID, skin);
|
||||||
}
|
|
||||||
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
||||||
}else {
|
}else {
|
||||||
processResolveURLTextureForOnline(initiator, playerUUID, t.textureUUID, t.texture,
|
processResolveURLTextureForOnline(initiator, playerUUID, t.textureUUID, t.texture,
|
||||||
|
@ -656,10 +635,7 @@ public class SkinService implements ISkinService {
|
||||||
@Override
|
@Override
|
||||||
public void accept(CacheFetchedProfile t) {
|
public void accept(CacheFetchedProfile t) {
|
||||||
if(t == null || t.texture == null) {
|
if(t == null || t.texture == null) {
|
||||||
CachedPlayerSkin skin;
|
CachedPlayerSkin skin = onlinePlayersCache.get(t.uuid);
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
skin = onlinePlayersCache.get(t.uuid);
|
|
||||||
}
|
|
||||||
if(skin != null) {
|
if(skin != null) {
|
||||||
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
||||||
}
|
}
|
||||||
|
@ -689,9 +665,7 @@ public class SkinService implements ISkinService {
|
||||||
mapUUID.getMostSignificantBits(), mapUUID.getLeastSignificantBits(),
|
mapUUID.getMostSignificantBits(), mapUUID.getLeastSignificantBits(),
|
||||||
SkinPackets.getModelId(t.model) == 1 ? 1 : 0), null, -1);
|
SkinPackets.getModelId(t.model) == 1 ? 1 : 0), null, -1);
|
||||||
}
|
}
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
onlinePlayersCache.put(mapUUID, skin);
|
onlinePlayersCache.put(mapUUID, skin);
|
||||||
}
|
|
||||||
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
||||||
}else {
|
}else {
|
||||||
processResolveURLTextureForOnline(initiator, mapUUID, t.textureUUID, t.texture,
|
processResolveURLTextureForOnline(initiator, mapUUID, t.textureUUID, t.texture,
|
||||||
|
@ -720,10 +694,7 @@ public class SkinService implements ISkinService {
|
||||||
@Override
|
@Override
|
||||||
public void accept(CacheFetchedProfile t) {
|
public void accept(CacheFetchedProfile t) {
|
||||||
if(t == null || t.texture == null) {
|
if(t == null || t.texture == null) {
|
||||||
CachedForeignSkin skin;
|
CachedForeignSkin skin = foreignSkinCache.get(playerUUID);
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
skin = foreignSkinCache.get(playerUUID);
|
|
||||||
}
|
|
||||||
if(skin != null) {
|
if(skin != null) {
|
||||||
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
||||||
}
|
}
|
||||||
|
@ -755,9 +726,7 @@ public class SkinService implements ISkinService {
|
||||||
SkinPackets.getModelId(t.model) == 1 ? 1 : 0),
|
SkinPackets.getModelId(t.model) == 1 ? 1 : 0),
|
||||||
-1);
|
-1);
|
||||||
}
|
}
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
foreignSkinCache.put(playerUUID, skin);
|
foreignSkinCache.put(playerUUID, skin);
|
||||||
}
|
|
||||||
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
initiator.sendEaglerMessage(skin.data.get(initiator.getEaglerProtocol()));
|
||||||
}else {
|
}else {
|
||||||
processResolveURLTextureForForeign(initiator, playerUUID, t.textureUUID, t.texture,
|
processResolveURLTextureForForeign(initiator, playerUUID, t.textureUUID, t.texture,
|
||||||
|
@ -777,28 +746,17 @@ public class SkinService implements ISkinService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerEaglercraftPlayer(UUID clientUUID, SkinPacketVersionCache generatedPacket, int modelId) {
|
public void registerEaglercraftPlayer(UUID clientUUID, SkinPacketVersionCache generatedPacket, int modelId) {
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
foreignSkinCache.remove(clientUUID);
|
foreignSkinCache.remove(clientUUID);
|
||||||
}
|
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
onlinePlayersCache.put(clientUUID, new CachedPlayerSkin(generatedPacket, null, modelId));
|
onlinePlayersCache.put(clientUUID, new CachedPlayerSkin(generatedPacket, null, modelId));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void unregisterPlayer(UUID clientUUID) {
|
public void unregisterPlayer(UUID clientUUID) {
|
||||||
CachedPlayerSkin data;
|
CachedPlayerSkin data = onlinePlayersCache.remove(clientUUID);
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
data = onlinePlayersCache.remove(clientUUID);
|
|
||||||
}
|
|
||||||
if(data != null) {
|
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) {
|
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);
|
deletePlayerTextureAssociation(clientUUID, data.textureUUID);
|
||||||
}else {
|
}else {
|
||||||
deletePlayerTextureAssociation(clientUUID, null);
|
deletePlayerTextureAssociation(clientUUID, null);
|
||||||
|
@ -807,94 +765,77 @@ public class SkinService implements ISkinService {
|
||||||
|
|
||||||
private void deletePlayerTextureAssociation(UUID clientUUID, UUID textureUUID) {
|
private void deletePlayerTextureAssociation(UUID clientUUID, UUID textureUUID) {
|
||||||
if(textureUUID != null) {
|
if(textureUUID != null) {
|
||||||
synchronized(onlinePlayersToTexturesMap) {
|
|
||||||
onlinePlayersToTexturesMap.remove(clientUUID);
|
onlinePlayersToTexturesMap.remove(clientUUID);
|
||||||
}
|
onlinePlayersFromTexturesMapLock.writeLock().lock();
|
||||||
synchronized(onlinePlayersFromTexturesMap) {
|
try {
|
||||||
onlinePlayersFromTexturesMap.remove(textureUUID, clientUUID);
|
onlinePlayersFromTexturesMap.remove(textureUUID, clientUUID);
|
||||||
|
}finally {
|
||||||
|
onlinePlayersFromTexturesMapLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
UUID removedUUID;
|
UUID removedUUID = onlinePlayersToTexturesMap.remove(clientUUID);
|
||||||
synchronized(onlinePlayersToTexturesMap) {
|
|
||||||
removedUUID = onlinePlayersToTexturesMap.remove(clientUUID);
|
|
||||||
}
|
|
||||||
if(removedUUID != null) {
|
if(removedUUID != null) {
|
||||||
synchronized(onlinePlayersFromTexturesMap) {
|
onlinePlayersFromTexturesMapLock.writeLock().lock();
|
||||||
|
try {
|
||||||
onlinePlayersFromTexturesMap.remove(removedUUID, clientUUID);
|
onlinePlayersFromTexturesMap.remove(removedUUID, clientUUID);
|
||||||
|
}finally {
|
||||||
|
onlinePlayersFromTexturesMapLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerTextureToPlayerAssociation(UUID textureUUID, UUID playerUUID) {
|
public void registerTextureToPlayerAssociation(UUID textureUUID, UUID playerUUID) {
|
||||||
synchronized(onlinePlayersFromTexturesMap) {
|
onlinePlayersFromTexturesMapLock.writeLock().lock();
|
||||||
|
try {
|
||||||
onlinePlayersFromTexturesMap.put(textureUUID, playerUUID);
|
onlinePlayersFromTexturesMap.put(textureUUID, playerUUID);
|
||||||
|
}finally {
|
||||||
|
onlinePlayersFromTexturesMapLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
synchronized(onlinePlayersToTexturesMap) {
|
|
||||||
onlinePlayersToTexturesMap.put(playerUUID, textureUUID);
|
onlinePlayersToTexturesMap.put(playerUUID, textureUUID);
|
||||||
}
|
CachedForeignSkin foreign = foreignSkinCache.remove(textureUUID);
|
||||||
CachedForeignSkin foreign;
|
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
foreign = foreignSkinCache.remove(textureUUID);
|
|
||||||
}
|
|
||||||
if(foreign != null) {
|
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, EaglerPlayerData eaglerHandler) {
|
public void processForceSkin(UUID playerUUID, EaglerPlayerData eaglerHandler) {
|
||||||
CachedPlayerSkin maybeCachedPacket;
|
CachedPlayerSkin maybeCachedPacket = onlinePlayersCache.get(playerUUID);
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
maybeCachedPacket = onlinePlayersCache.get(playerUUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(maybeCachedPacket != null) {
|
if(maybeCachedPacket != null) {
|
||||||
eaglerHandler.sendEaglerMessage(maybeCachedPacket.data.getForceClientV4());
|
eaglerHandler.sendEaglerMessage(maybeCachedPacket.data.getForceClientV4());
|
||||||
}else {
|
}else {
|
||||||
UUID playerTexture;
|
UUID playerTexture = onlinePlayersToTexturesMap.get(playerUUID);
|
||||||
synchronized(onlinePlayersToTexturesMap) {
|
|
||||||
playerTexture = onlinePlayersToTexturesMap.get(playerUUID);
|
|
||||||
}
|
|
||||||
if(playerTexture != null) {
|
if(playerTexture != null) {
|
||||||
Collection<UUID> possiblePlayers;
|
Collection<UUID> possiblePlayers;
|
||||||
synchronized(onlinePlayersFromTexturesMap) {
|
onlinePlayersFromTexturesMapLock.readLock().lock();
|
||||||
possiblePlayers = onlinePlayersFromTexturesMap.get(playerTexture);
|
try {
|
||||||
|
possiblePlayers = new ArrayList<>(onlinePlayersFromTexturesMap.get(playerTexture));
|
||||||
|
}finally {
|
||||||
|
onlinePlayersFromTexturesMapLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
boolean playersExist = possiblePlayers.size() > 0;
|
boolean playersExist = possiblePlayers.size() > 0;
|
||||||
if(playersExist) {
|
if(playersExist) {
|
||||||
for(UUID uuid : possiblePlayers) {
|
for(UUID uuid : possiblePlayers) {
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
maybeCachedPacket = onlinePlayersCache.get(uuid);
|
maybeCachedPacket = onlinePlayersCache.get(uuid);
|
||||||
}
|
|
||||||
if(maybeCachedPacket != null) {
|
if(maybeCachedPacket != null) {
|
||||||
SkinPacketVersionCache rewritten = SkinPacketVersionCache.rewriteUUID(
|
SkinPacketVersionCache rewritten = SkinPacketVersionCache.rewriteUUID(
|
||||||
maybeCachedPacket.data, playerUUID.getMostSignificantBits(),
|
maybeCachedPacket.data, playerUUID.getMostSignificantBits(),
|
||||||
playerUUID.getLeastSignificantBits());
|
playerUUID.getLeastSignificantBits());
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
onlinePlayersCache.put(playerUUID, new CachedPlayerSkin(rewritten,
|
onlinePlayersCache.put(playerUUID, new CachedPlayerSkin(rewritten,
|
||||||
maybeCachedPacket.textureUUID, maybeCachedPacket.modelId));
|
maybeCachedPacket.textureUUID, maybeCachedPacket.modelId));
|
||||||
}
|
|
||||||
eaglerHandler.sendEaglerMessage(rewritten.getForceClientV4());
|
eaglerHandler.sendEaglerMessage(rewritten.getForceClientV4());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CachedForeignSkin foreignSkin;
|
CachedForeignSkin foreignSkin = foreignSkinCache.get(playerTexture);
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
foreignSkin = foreignSkinCache.get(playerTexture);
|
|
||||||
}
|
|
||||||
if(foreignSkin != null && foreignSkin.modelKnown != -1) {
|
if(foreignSkin != null && foreignSkin.modelKnown != -1) {
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
onlinePlayersCache.put(playerUUID,
|
onlinePlayersCache.put(playerUUID,
|
||||||
new CachedPlayerSkin(SkinPacketVersionCache.rewriteUUID(foreignSkin.data,
|
new CachedPlayerSkin(SkinPacketVersionCache.rewriteUUID(foreignSkin.data,
|
||||||
playerUUID.getMostSignificantBits(), playerUUID.getLeastSignificantBits()),
|
playerUUID.getMostSignificantBits(), playerUUID.getLeastSignificantBits()),
|
||||||
playerTexture, foreignSkin.modelKnown));
|
playerTexture, foreignSkin.modelKnown));
|
||||||
}
|
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
foreignSkinCache.remove(playerTexture);
|
foreignSkinCache.remove(playerTexture);
|
||||||
}
|
|
||||||
eaglerHandler.sendEaglerMessage(foreignSkin.data.getForceClientV4());
|
eaglerHandler.sendEaglerMessage(foreignSkin.data.getForceClientV4());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -913,7 +854,7 @@ public class SkinService implements ISkinService {
|
||||||
if(skinObj != null) {
|
if(skinObj != null) {
|
||||||
JsonElement url = json.get("url");
|
JsonElement url = json.get("url");
|
||||||
if(url != null) {
|
if(url != null) {
|
||||||
String urlStr = SkinService.sanitizeTextureURL(url.getAsString());
|
String urlStr = sanitizeTextureURL(url.getAsString());
|
||||||
if(urlStr == null) {
|
if(urlStr == null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -927,19 +868,14 @@ public class SkinService implements ISkinService {
|
||||||
}
|
}
|
||||||
UUID skinUUID = SkinPackets.createEaglerURLSkinUUID(urlStr);
|
UUID skinUUID = SkinPackets.createEaglerURLSkinUUID(urlStr);
|
||||||
|
|
||||||
CachedForeignSkin foreignSkin;
|
CachedForeignSkin foreignSkin = foreignSkinCache.remove(skinUUID);
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
foreignSkin = foreignSkinCache.remove(skinUUID);
|
|
||||||
}
|
|
||||||
if(foreignSkin != null) {
|
if(foreignSkin != null) {
|
||||||
registerTextureToPlayerAssociation(skinUUID, playerUUID);
|
registerTextureToPlayerAssociation(skinUUID, playerUUID);
|
||||||
SkinPacketVersionCache rewrite = SkinPacketVersionCache
|
SkinPacketVersionCache rewrite = SkinPacketVersionCache
|
||||||
.rewriteUUIDModel(foreignSkin.data,
|
.rewriteUUIDModel(foreignSkin.data,
|
||||||
playerUUID.getMostSignificantBits(),
|
playerUUID.getMostSignificantBits(),
|
||||||
playerUUID.getLeastSignificantBits(), model);
|
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());
|
eaglerHandler.sendEaglerMessage(rewrite.getForceClientV4());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -967,10 +903,7 @@ public class SkinService implements ISkinService {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}else {
|
}else {
|
||||||
CachedForeignSkin foreignSkin;
|
CachedForeignSkin foreignSkin = foreignSkinCache.get(playerUUID);
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
foreignSkin = foreignSkinCache.get(playerUUID);
|
|
||||||
}
|
|
||||||
if(foreignSkin != null) {
|
if(foreignSkin != null) {
|
||||||
foreignSkin.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
foreignSkin.lastHit = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
||||||
eaglerHandler.sendEaglerMessage(foreignSkin.data.getForceClientV4());
|
eaglerHandler.sendEaglerMessage(foreignSkin.data.getForceClientV4());
|
||||||
|
@ -997,10 +930,7 @@ public class SkinService implements ISkinService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(byte[] t) {
|
public void accept(byte[] t) {
|
||||||
CachedPlayerSkin skin;
|
CachedPlayerSkin skin = onlinePlayersCache.get(onlineCacheUUID);
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
skin = onlinePlayersCache.get(onlineCacheUUID);
|
|
||||||
}
|
|
||||||
if(skin != null) {
|
if(skin != null) {
|
||||||
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
||||||
}
|
}
|
||||||
|
@ -1027,9 +957,7 @@ public class SkinService implements ISkinService {
|
||||||
onlineCacheUUID.getMostSignificantBits(),
|
onlineCacheUUID.getMostSignificantBits(),
|
||||||
onlineCacheUUID.getLeastSignificantBits()), null, -1);
|
onlineCacheUUID.getLeastSignificantBits()), null, -1);
|
||||||
}
|
}
|
||||||
synchronized (onlinePlayersCache) {
|
|
||||||
onlinePlayersCache.put(onlineCacheUUID, skin);
|
onlinePlayersCache.put(onlineCacheUUID, skin);
|
||||||
}
|
|
||||||
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1054,10 +982,7 @@ public class SkinService implements ISkinService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(byte[] t) {
|
public void accept(byte[] t) {
|
||||||
CachedForeignSkin skin;
|
CachedForeignSkin skin = foreignSkinCache.get(foreignCacheUUID);
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
skin = foreignSkinCache.get(foreignCacheUUID);
|
|
||||||
}
|
|
||||||
if(skin != null) {
|
if(skin != null) {
|
||||||
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
||||||
}
|
}
|
||||||
|
@ -1085,9 +1010,7 @@ public class SkinService implements ISkinService {
|
||||||
foreignCacheUUID.getLeastSignificantBits()),
|
foreignCacheUUID.getLeastSignificantBits()),
|
||||||
-1);
|
-1);
|
||||||
}
|
}
|
||||||
synchronized (foreignSkinCache) {
|
|
||||||
foreignSkinCache.put(foreignCacheUUID, skin);
|
foreignSkinCache.put(foreignCacheUUID, skin);
|
||||||
}
|
|
||||||
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1112,10 +1035,7 @@ public class SkinService implements ISkinService {
|
||||||
@Override
|
@Override
|
||||||
public void accept(CacheFetchedProfile t) {
|
public void accept(CacheFetchedProfile t) {
|
||||||
if(t == null || t.texture == null) {
|
if(t == null || t.texture == null) {
|
||||||
CachedPlayerSkin skin;
|
CachedPlayerSkin skin = onlinePlayersCache.get(playerUUID);
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
skin = onlinePlayersCache.get(playerUUID);
|
|
||||||
}
|
|
||||||
if(skin != null) {
|
if(skin != null) {
|
||||||
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
||||||
}
|
}
|
||||||
|
@ -1147,9 +1067,7 @@ public class SkinService implements ISkinService {
|
||||||
SkinPackets.getModelId(t.model) == 1 ? 1 : 0),
|
SkinPackets.getModelId(t.model) == 1 ? 1 : 0),
|
||||||
null, -1);
|
null, -1);
|
||||||
}
|
}
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
onlinePlayersCache.put(playerUUID, skin);
|
onlinePlayersCache.put(playerUUID, skin);
|
||||||
}
|
|
||||||
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
||||||
}else {
|
}else {
|
||||||
processResolveURLTextureForOnlineToForce(initiator, playerUUID, t.textureUUID, t.texture,
|
processResolveURLTextureForOnlineToForce(initiator, playerUUID, t.textureUUID, t.texture,
|
||||||
|
@ -1178,10 +1096,7 @@ public class SkinService implements ISkinService {
|
||||||
@Override
|
@Override
|
||||||
public void accept(CacheFetchedProfile t) {
|
public void accept(CacheFetchedProfile t) {
|
||||||
if(t == null || t.texture == null) {
|
if(t == null || t.texture == null) {
|
||||||
CachedPlayerSkin skin;
|
CachedPlayerSkin skin = onlinePlayersCache.get(t.uuid);
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
skin = onlinePlayersCache.get(t.uuid);
|
|
||||||
}
|
|
||||||
if(skin != null) {
|
if(skin != null) {
|
||||||
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
||||||
}
|
}
|
||||||
|
@ -1211,9 +1126,7 @@ public class SkinService implements ISkinService {
|
||||||
mapUUID.getMostSignificantBits(), mapUUID.getLeastSignificantBits(),
|
mapUUID.getMostSignificantBits(), mapUUID.getLeastSignificantBits(),
|
||||||
SkinPackets.getModelId(t.model) == 1 ? 1 : 0), null, -1);
|
SkinPackets.getModelId(t.model) == 1 ? 1 : 0), null, -1);
|
||||||
}
|
}
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
onlinePlayersCache.put(mapUUID, skin);
|
onlinePlayersCache.put(mapUUID, skin);
|
||||||
}
|
|
||||||
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
||||||
}else {
|
}else {
|
||||||
processResolveURLTextureForOnlineToForce(initiator, mapUUID, t.textureUUID, t.texture,
|
processResolveURLTextureForOnlineToForce(initiator, mapUUID, t.textureUUID, t.texture,
|
||||||
|
@ -1242,10 +1155,7 @@ public class SkinService implements ISkinService {
|
||||||
@Override
|
@Override
|
||||||
public void accept(CacheFetchedProfile t) {
|
public void accept(CacheFetchedProfile t) {
|
||||||
if(t == null || t.texture == null) {
|
if(t == null || t.texture == null) {
|
||||||
CachedForeignSkin skin;
|
CachedForeignSkin skin = foreignSkinCache.get(playerUUID);
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
skin = foreignSkinCache.get(playerUUID);
|
|
||||||
}
|
|
||||||
if(skin != null) {
|
if(skin != null) {
|
||||||
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
||||||
}
|
}
|
||||||
|
@ -1277,9 +1187,7 @@ public class SkinService implements ISkinService {
|
||||||
SkinPackets.getModelId(t.model) == 1 ? 1 : 0),
|
SkinPackets.getModelId(t.model) == 1 ? 1 : 0),
|
||||||
-1);
|
-1);
|
||||||
}
|
}
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
foreignSkinCache.put(playerUUID, skin);
|
foreignSkinCache.put(playerUUID, skin);
|
||||||
}
|
|
||||||
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
initiator.sendEaglerMessage(skin.data.getForceClientV4());
|
||||||
}else {
|
}else {
|
||||||
processResolveURLTextureForForeignToForce(initiator, playerUUID, t.textureUUID, t.texture,
|
processResolveURLTextureForForeignToForce(initiator, playerUUID, t.textureUUID, t.texture,
|
||||||
|
@ -1301,12 +1209,16 @@ public class SkinService implements ISkinService {
|
||||||
public void flush() {
|
public void flush() {
|
||||||
long millis = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
long millis = EaglerXVelocityAPIHelper.steadyTimeMillis();
|
||||||
|
|
||||||
synchronized(foreignSkinCache) {
|
final List<UUID> foreignSkinCleanup = new ArrayList<>(4);
|
||||||
Iterator<CachedForeignSkin> itr = foreignSkinCache.values().iterator();
|
foreignSkinCache.entrySet().forEach((etr) -> {
|
||||||
while(itr.hasNext()) {
|
if(millis - etr.getValue().lastHit > 900000l) { // 15 minutes
|
||||||
if(millis - itr.next().lastHit > 900000l) { // 15 minutes
|
foreignSkinCleanup.add(etr.getKey());
|
||||||
itr.remove();
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!foreignSkinCleanup.isEmpty()) {
|
||||||
|
for(UUID uuid : foreignSkinCleanup) {
|
||||||
|
foreignSkinCache.remove(uuid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1357,7 +1269,8 @@ public class SkinService implements ISkinService {
|
||||||
elapsedCooldown /= cooldownPeriod;
|
elapsedCooldown /= cooldownPeriod;
|
||||||
if(elapsedCooldown > 0) {
|
if(elapsedCooldown > 0) {
|
||||||
antagonistCooldown += elapsedCooldown * cooldownPeriod;
|
antagonistCooldown += elapsedCooldown * cooldownPeriod;
|
||||||
synchronized(antagonists) {
|
antagonistsLock.writeLock().lock();
|
||||||
|
try {
|
||||||
Iterator<UUID> itr = antagonists.keySet().iterator();
|
Iterator<UUID> itr = antagonists.keySet().iterator();
|
||||||
while(itr.hasNext()) {
|
while(itr.hasNext()) {
|
||||||
UUID key = itr.next();
|
UUID key = itr.next();
|
||||||
|
@ -1368,6 +1281,8 @@ public class SkinService implements ISkinService {
|
||||||
antagonists.put(key, i);
|
antagonists.put(key, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}finally {
|
||||||
|
antagonistsLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1375,10 +1290,7 @@ public class SkinService implements ISkinService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkinPacketVersionCache getSkin(UUID playerUUID) {
|
public SkinPacketVersionCache getSkin(UUID playerUUID) {
|
||||||
CachedPlayerSkin skin;
|
CachedPlayerSkin skin = onlinePlayersCache.get(playerUUID);
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
skin = onlinePlayersCache.get(playerUUID);
|
|
||||||
}
|
|
||||||
return skin != null ? skin.data : null;
|
return skin != null ? skin.data : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1393,25 +1305,26 @@ public class SkinService implements ISkinService {
|
||||||
private boolean isLimitedAsAntagonist(UUID uuid) {
|
private boolean isLimitedAsAntagonist(UUID uuid) {
|
||||||
int limit = EaglerXVelocity.getEagler().getConfig().getAntagonistsRateLimit();
|
int limit = EaglerXVelocity.getEagler().getConfig().getAntagonistsRateLimit();
|
||||||
limit += limit >> 1;
|
limit += limit >> 1;
|
||||||
synchronized(antagonists) {
|
int i;
|
||||||
int i = antagonists.getInt(uuid);
|
antagonistsLock.readLock().lock();
|
||||||
return i != antagonists.defaultReturnValue() && i > limit;
|
try {
|
||||||
|
i = antagonists.getInt(uuid);
|
||||||
|
}finally {
|
||||||
|
antagonistsLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
|
return i != antagonists.defaultReturnValue() && i > limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resetMaps() {
|
private void resetMaps() {
|
||||||
synchronized(onlinePlayersCache) {
|
|
||||||
onlinePlayersCache.clear();
|
onlinePlayersCache.clear();
|
||||||
}
|
onlinePlayersFromTexturesMapLock.writeLock().lock();
|
||||||
synchronized(onlinePlayersFromTexturesMap) {
|
try {
|
||||||
onlinePlayersFromTexturesMap.clear();
|
onlinePlayersFromTexturesMap.clear();
|
||||||
|
}finally {
|
||||||
|
onlinePlayersFromTexturesMapLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
synchronized(onlinePlayersToTexturesMap) {
|
|
||||||
onlinePlayersToTexturesMap.clear();
|
onlinePlayersToTexturesMap.clear();
|
||||||
}
|
|
||||||
synchronized(foreignSkinCache) {
|
|
||||||
foreignSkinCache.clear();
|
foreignSkinCache.clear();
|
||||||
}
|
|
||||||
synchronized(pendingTextures) {
|
synchronized(pendingTextures) {
|
||||||
pendingTextures.clear();
|
pendingTextures.clear();
|
||||||
}
|
}
|
||||||
|
@ -1421,8 +1334,11 @@ public class SkinService implements ISkinService {
|
||||||
synchronized(pendingNameLookups) {
|
synchronized(pendingNameLookups) {
|
||||||
pendingNameLookups.clear();
|
pendingNameLookups.clear();
|
||||||
}
|
}
|
||||||
synchronized(antagonists) {
|
antagonistsLock.writeLock().lock();
|
||||||
|
try {
|
||||||
antagonists.clear();
|
antagonists.clear();
|
||||||
|
}finally {
|
||||||
|
antagonistsLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1439,7 +1355,7 @@ public class SkinService implements ISkinService {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String host = uri.getHost();
|
String host = uri.getHost();
|
||||||
if(host == null) {
|
if(host == null || !EaglerXVelocity.getEagler().getConfig().isValidSkinHost(host)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
scheme = scheme.toLowerCase();
|
scheme = scheme.toLowerCase();
|
||||||
|
|
|
@ -1,20 +1,15 @@
|
||||||
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins;
|
package net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.skins;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import com.google.common.collect.Multimap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import com.google.common.collect.MultimapBuilder;
|
|
||||||
|
|
||||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData;
|
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.server.EaglerPlayerData;
|
||||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinPresetEAG;
|
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketOtherSkinPresetEAG;
|
||||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache;
|
import net.lax1dude.eaglercraft.v1_8.socket.protocol.util.SkinPacketVersionCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
* 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
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
@ -44,22 +39,15 @@ public class SkinServiceOffline implements ISkinService {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map<UUID, CachedSkin> skinCache = new HashMap<>();
|
private final ConcurrentMap<UUID, CachedSkin> skinCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final Multimap<UUID, UUID> onlinePlayersFromTexturesMap = MultimapBuilder.hashKeys().hashSetValues().build();
|
|
||||||
|
|
||||||
public void init(String uri, String driverClass, String driverPath, int keepObjectsDays, int keepProfilesDays,
|
public void init(String uri, String driverClass, String driverPath, int keepObjectsDays, int keepProfilesDays,
|
||||||
int maxObjects, int maxProfiles) {
|
int maxObjects, int maxProfiles) {
|
||||||
synchronized(skinCache) {
|
|
||||||
skinCache.clear();
|
skinCache.clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void processGetOtherSkin(UUID searchUUID, EaglerPlayerData sender) {
|
public void processGetOtherSkin(UUID searchUUID, EaglerPlayerData sender) {
|
||||||
CachedSkin cached;
|
CachedSkin cached = skinCache.get(searchUUID);
|
||||||
synchronized(skinCache) {
|
|
||||||
cached = skinCache.get(searchUUID);
|
|
||||||
}
|
|
||||||
if(cached != null) {
|
if(cached != null) {
|
||||||
sender.sendEaglerMessage(cached.packet.get(sender.getEaglerProtocol()));
|
sender.sendEaglerMessage(cached.packet.get(sender.getEaglerProtocol()));
|
||||||
}else {
|
}else {
|
||||||
|
@ -69,24 +57,6 @@ public class SkinServiceOffline implements ISkinService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processGetOtherSkin(UUID searchUUID, String skinURL, EaglerPlayerData sender) {
|
public void processGetOtherSkin(UUID searchUUID, String skinURL, EaglerPlayerData sender) {
|
||||||
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) {
|
|
||||||
sender.sendEaglerMessage(cached.packet.get(sender.getEaglerProtocol(),
|
|
||||||
searchUUID.getMostSignificantBits(), searchUUID.getLeastSignificantBits()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(skinURL.startsWith("eagler://")) { // customs skulls from exported singleplayer worlds
|
if(skinURL.startsWith("eagler://")) { // customs skulls from exported singleplayer worlds
|
||||||
sender.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(),
|
sender.sendEaglerMessage(new SPacketOtherSkinPresetEAG(searchUUID.getMostSignificantBits(),
|
||||||
searchUUID.getLeastSignificantBits(), 0));
|
searchUUID.getLeastSignificantBits(), 0));
|
||||||
|
@ -97,28 +67,21 @@ public class SkinServiceOffline implements ISkinService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerEaglercraftPlayer(UUID clientUUID, SkinPacketVersionCache generatedPacket, int modelId) {
|
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) {
|
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) {
|
public void registerTextureToPlayerAssociation(UUID textureUUID, UUID playerUUID) {
|
||||||
synchronized(onlinePlayersFromTexturesMap) {
|
|
||||||
onlinePlayersFromTexturesMap.put(textureUUID, playerUUID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processForceSkin(UUID playerUUID, EaglerPlayerData initialHandler) {
|
public void processForceSkin(UUID playerUUID, EaglerPlayerData initialHandler) {
|
||||||
CachedSkin cached;
|
CachedSkin cached = skinCache.get(playerUUID);
|
||||||
synchronized(skinCache) {
|
|
||||||
cached = skinCache.get(playerUUID);
|
|
||||||
}
|
|
||||||
if(cached != null) {
|
if(cached != null) {
|
||||||
initialHandler.sendEaglerMessage(cached.packet.getForceClientV4());
|
initialHandler.sendEaglerMessage(cached.packet.getForceClientV4());
|
||||||
}
|
}
|
||||||
|
@ -129,16 +92,11 @@ public class SkinServiceOffline implements ISkinService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
synchronized(skinCache) {
|
|
||||||
skinCache.clear();
|
skinCache.clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public SkinPacketVersionCache getSkin(UUID playerUUID) {
|
public SkinPacketVersionCache getSkin(UUID playerUUID) {
|
||||||
CachedSkin cached;
|
CachedSkin cached = skinCache.get(playerUUID);
|
||||||
synchronized(skinCache) {
|
|
||||||
cached = skinCache.get(playerUUID);
|
|
||||||
}
|
|
||||||
return cached != null ? cached.packet : null;
|
return cached != null ? cached.packet : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"id":"eaglerxvelocity","name":"EaglercraftXVelocity","version":"1.1.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","authors":["lax1dude", "ayunami2000"],"dependencies":[],"main":"net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity"}
|
{"id":"eaglerxvelocity","name":"EaglercraftXVelocity","version":"1.1.6","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","authors":["lax1dude", "ayunami2000"],"dependencies":[],"main":"net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity"}
|
|
@ -1 +1 @@
|
||||||
1.1.5
|
1.1.6
|
Loading…
Reference in a new issue