diff --git a/CraftBukkit-Patches/0133-Convert-player-skulls-async.patch b/CraftBukkit-Patches/0133-Convert-player-skulls-async.patch index 3f8e4a2177..53dc998189 100644 --- a/CraftBukkit-Patches/0133-Convert-player-skulls-async.patch +++ b/CraftBukkit-Patches/0133-Convert-player-skulls-async.patch @@ -121,19 +121,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + GameProfileLookup gameProfileLookup = new GameProfileLookup(profiles); + + MinecraftServer.getServer().getGameProfileRepository().findProfilesByNames(new String[] { key }, Agent.MINECRAFT, gameProfileLookup); -+ if (!MinecraftServer.getServer().getOnlineMode() && profiles[0] == null) { ++ ++ GameProfile profile = profiles[ 0 ]; ++ if (profile == null) { + UUID uuid = EntityHuman.a(new GameProfile(null, key)); -+ GameProfile profile = new GameProfile(uuid, key); ++ profile = new GameProfile(uuid, key); + + gameProfileLookup.onProfileLookupSucceeded(profile); -+ } ++ } else ++ { + -+ GameProfile profile = profiles[0]; ++ Property property = Iterables.getFirst( profile.getProperties().get( "textures" ), null ); + -+ Property property = Iterables.getFirst(profile.getProperties().get("textures"), null); -+ -+ if (property == null) { -+ profile = MinecraftServer.getServer().av().fillProfileProperties(profile, true); ++ if ( property == null ) ++ { ++ profile = MinecraftServer.getServer().av().fillProfileProperties( profile, true ); ++ } + } + + diff --git a/CraftBukkit-Patches/0168-Set-the-minimum-max-health-attribute-value-to-0.1.patch b/CraftBukkit-Patches/0168-Set-the-minimum-max-health-attribute-value-to-0.1.patch new file mode 100644 index 0000000000..6efb24c5dd --- /dev/null +++ b/CraftBukkit-Patches/0168-Set-the-minimum-max-health-attribute-value-to-0.1.patch @@ -0,0 +1,20 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Mon, 28 Jul 2014 23:15:00 +0100 +Subject: [PATCH] Set the minimum max health attribute value to 0.1 + + +diff --git a/src/main/java/net/minecraft/server/GenericAttributes.java b/src/main/java/net/minecraft/server/GenericAttributes.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/GenericAttributes.java ++++ b/src/main/java/net/minecraft/server/GenericAttributes.java +@@ -0,0 +0,0 @@ public class GenericAttributes { + + private static final Logger f = LogManager.getLogger(); + // Spigot Start +- public static final IAttribute maxHealth = (new AttributeRanged("generic.maxHealth", 20.0D, 0.0D, org.spigotmc.SpigotConfig.maxHealth)).a("Max Health").a(true); ++ public static final IAttribute maxHealth = (new AttributeRanged("generic.maxHealth", 20.0D, 0.1D, org.spigotmc.SpigotConfig.maxHealth)).a("Max Health").a(true); // Spigot + public static final IAttribute b = (new AttributeRanged("generic.followRange", 32.0D, 0.0D, 2048.0D)).a("Follow Range"); + public static final IAttribute c = (new AttributeRanged("generic.knockbackResistance", 0.0D, 0.0D, 1.0D)).a("Knockback Resistance"); + public static final IAttribute d = (new AttributeRanged("generic.movementSpeed", 0.699999988079071D, 0.0D, org.spigotmc.SpigotConfig.movementSpeed)).a("Movement Speed").a(true); +-- \ No newline at end of file diff --git a/CraftBukkit-Patches/0169-Add-an-option-for-a-global-cache-for-any-request-on-.patch b/CraftBukkit-Patches/0169-Add-an-option-for-a-global-cache-for-any-request-on-.patch new file mode 100644 index 0000000000..99f6733a0a --- /dev/null +++ b/CraftBukkit-Patches/0169-Add-an-option-for-a-global-cache-for-any-request-on-.patch @@ -0,0 +1,286 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Thinkofdeath +Date: Mon, 28 Jul 2014 11:42:11 +0100 +Subject: [PATCH] Add an option for a global cache for any request on Mojang's + api to handle plugins that don't use UserCache (or any cache) + + +diff --git a/src/main/java/org/spigotmc/CachedMojangAPIConnection.java b/src/main/java/org/spigotmc/CachedMojangAPIConnection.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/CachedMojangAPIConnection.java +@@ -0,0 +0,0 @@ ++package org.spigotmc; ++ ++import com.google.common.base.Charsets; ++import com.google.gson.JsonArray; ++import com.google.gson.JsonElement; ++import com.google.gson.JsonObject; ++import com.google.gson.JsonParser; ++import net.minecraft.util.com.google.common.cache.Cache; ++import net.minecraft.util.com.google.common.cache.CacheBuilder; ++ ++import java.io.ByteArrayInputStream; ++import java.io.ByteArrayOutputStream; ++import java.io.IOException; ++import java.io.InputStream; ++import java.io.InputStreamReader; ++import java.io.OutputStream; ++import java.net.HttpURLConnection; ++import java.net.Proxy; ++import java.net.URL; ++import java.util.concurrent.TimeUnit; ++ ++public class CachedMojangAPIConnection extends HttpURLConnection ++{ ++ private final CachedStreamHandlerFactory.CachedStreamHandler cachedStreamHandler; ++ private final Proxy proxy; ++ private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ++ private ByteArrayInputStream inputStream; ++ private boolean outClosed = false; ++ ++ private static final Cache cache = CacheBuilder.newBuilder() ++ .maximumSize( 10000 ) ++ .expireAfterAccess( 1, TimeUnit.HOURS ) ++ .build(); ++ ++ public CachedMojangAPIConnection(CachedStreamHandlerFactory.CachedStreamHandler cachedStreamHandler, URL url, Proxy proxy) ++ { ++ super( url ); ++ this.cachedStreamHandler = cachedStreamHandler; ++ this.proxy = proxy; ++ } ++ ++ @Override ++ public void disconnect() ++ { ++ ++ } ++ ++ @Override ++ public boolean usingProxy() ++ { ++ return proxy != null; ++ } ++ ++ @Override ++ public void connect() throws IOException ++ { ++ ++ } ++ ++ @Override ++ public InputStream getInputStream() throws IOException ++ { ++ if ( inputStream == null ) ++ { ++ outClosed = true; ++ JsonArray users = new JsonParser().parse( new String( outputStream.toByteArray(), Charsets.UTF_8 ) ).getAsJsonArray(); ++ StringBuilder reply = new StringBuilder( "[" ); ++ StringBuilder missingUsers = new StringBuilder( "[" ); ++ for ( JsonElement user : users ) ++ { ++ String username = user.getAsString().toLowerCase(); ++ String info = cache.getIfPresent( username ); ++ if ( info != null ) ++ { ++ reply.append( info ).append( "," ); ++ } else ++ { ++ missingUsers ++ .append( "\"" ) ++ .append( username ) ++ .append( "\"" ) ++ .append( "," ); ++ } ++ } ++ missingUsers.deleteCharAt( missingUsers.length() - 1 ).append( "]" ); ++ HttpURLConnection connection; ++ if ( proxy == null ) ++ { ++ connection = (HttpURLConnection) cachedStreamHandler.getDefaultConnection( url ); ++ } else ++ { ++ connection = (HttpURLConnection) cachedStreamHandler.getDefaultConnection( url, proxy ); ++ } ++ connection.setRequestMethod( "POST" ); ++ connection.setRequestProperty( "Content-Type", "application/json" ); ++ connection.setDoInput( true ); ++ connection.setDoOutput( true ); ++ OutputStream out = connection.getOutputStream(); ++ out.write( missingUsers.toString().getBytes( Charsets.UTF_8 ) ); ++ out.flush(); ++ out.close(); ++ JsonArray newUsers = new JsonParser().parse( new InputStreamReader( connection.getInputStream(), Charsets.UTF_8 ) ).getAsJsonArray(); ++ for ( JsonElement user : newUsers ) ++ { ++ JsonObject u = user.getAsJsonObject(); ++ cache.put( u.get( "name" ).getAsString(), u.toString() ); ++ reply.append( u.toString() ).append( "," ); ++ } ++ reply.deleteCharAt( reply.length() - 1 ); ++ inputStream = new ByteArrayInputStream( reply.append( "]" ).toString().getBytes( Charsets.UTF_8 ) ); ++ } ++ return inputStream; ++ } ++ ++ @Override ++ public OutputStream getOutputStream() throws IOException ++ { ++ if ( outClosed ) ++ { ++ throw new RuntimeException( "Write after send" ); ++ } ++ return outputStream; ++ } ++} +diff --git a/src/main/java/org/spigotmc/CachedStreamHandlerFactory.java b/src/main/java/org/spigotmc/CachedStreamHandlerFactory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/org/spigotmc/CachedStreamHandlerFactory.java +@@ -0,0 +0,0 @@ ++package org.spigotmc; ++ ++import java.io.IOException; ++import java.lang.reflect.InvocationTargetException; ++import java.lang.reflect.Method; ++import java.net.Proxy; ++import java.net.URL; ++import java.net.URLConnection; ++import java.net.URLStreamHandler; ++import java.net.URLStreamHandlerFactory; ++ ++public class CachedStreamHandlerFactory implements URLStreamHandlerFactory ++{ ++ @Override ++ public URLStreamHandler createURLStreamHandler(String protocol) ++ { ++ if ( protocol.equals( "http" ) || protocol.equals( "https" ) ) ++ { ++ return new CachedStreamHandler( protocol ); ++ } ++ return null; ++ } ++ ++ public class CachedStreamHandler extends URLStreamHandler ++ { ++ private final String protocol; ++ private final URLStreamHandler handler; ++ private final Method openCon; ++ private final Method openConProxy; ++ ++ public CachedStreamHandler(String protocol) ++ { ++ this.protocol = protocol; ++ if ( protocol.equals( "http" ) ) ++ { ++ handler = new sun.net.www.protocol.http.Handler(); ++ } else ++ { ++ handler = new sun.net.www.protocol.https.Handler(); ++ } ++ try ++ { ++ openCon = handler.getClass().getDeclaredMethod( "openConnection", URL.class ); ++ openCon.setAccessible( true ); ++ openConProxy = handler.getClass().getDeclaredMethod( "openConnection", URL.class, Proxy.class ); ++ openConProxy.setAccessible( true ); ++ } catch ( NoSuchMethodException e ) ++ { ++ throw new RuntimeException( e ); ++ } ++ } ++ ++ @Override ++ protected URLConnection openConnection(URL u) throws IOException ++ { ++ if ( u.getHost().equals( "api.mojang.com" ) ++ || u.getPath().startsWith( "/profiles/minecraft" ) ) ++ { ++ return cachedConnection( u ); ++ } ++ return getDefaultConnection( u ); ++ } ++ ++ @Override ++ protected URLConnection openConnection(URL u, Proxy p) throws IOException ++ { ++ if ( u.getHost().equals( "api.mojang.com" ) ++ || u.getPath().startsWith( "/profiles/minecraft" ) ) ++ { ++ return cachedConnection( u, p ); ++ } ++ return getDefaultConnection( u, p ); ++ } ++ ++ private URLConnection cachedConnection(URL u) ++ { ++ return cachedConnection( u, null ); ++ } ++ ++ private URLConnection cachedConnection(URL u, Proxy p) ++ { ++ return new CachedMojangAPIConnection( this, u, p ); ++ } ++ ++ public URLConnection getDefaultConnection(URL u) ++ { ++ try ++ { ++ return (URLConnection) openCon.invoke( handler, u ); ++ } catch ( IllegalAccessException e ) ++ { ++ e.printStackTrace(); ++ } catch ( InvocationTargetException e ) ++ { ++ e.printStackTrace(); ++ } ++ return null; ++ } ++ ++ public URLConnection getDefaultConnection(URL u, Proxy p) ++ { ++ try ++ { ++ return (URLConnection) openConProxy.invoke( handler, u, p ); ++ } catch ( IllegalAccessException e ) ++ { ++ e.printStackTrace(); ++ } catch ( InvocationTargetException e ) ++ { ++ e.printStackTrace(); ++ } ++ return null; ++ } ++ } ++} +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -0,0 +0,0 @@ import java.io.IOException; + import java.lang.reflect.InvocationTargetException; + import java.lang.reflect.Method; + import java.lang.reflect.Modifier; ++import java.net.URL; + import java.util.Arrays; + import java.util.HashMap; + import java.util.HashSet; +@@ -0,0 +0,0 @@ public class SpigotConfig + attackDamage = getDouble( "settings.attribute.attackDamage.max", attackDamage ); + ( (AttributeRanged) GenericAttributes.e ).b = attackDamage; + } ++ ++ private static void globalAPICache() ++ { ++ if ( getBoolean( "settings.global-api-cache", false ) ) ++ { ++ Bukkit.getLogger().info( "Global API cache enabled - All requests to Mojang's API will be " + ++ "handled by Spigot" ); ++ URL.setURLStreamHandlerFactory(new CachedStreamHandlerFactory()); ++ } ++ } + } +-- \ No newline at end of file