diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..1d1204e3 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,24 @@ +name: Build nPaper + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 8 + uses: actions/setup-java@v3 + with: + java-version: '8' + distribution: 'temurin' + cache: maven + - name: Build nPaper + run: mvn clean install + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: nPaper + path: ./nPaper-Server/target/npaper-1.7.10-R0.1-SNAPSHOT.jar \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6c8fe8d1..d5111f57 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,7 @@ nbproject/ nbactions.xml # we use maven! -build.xml +pom.xml # maven target/ @@ -37,4 +37,8 @@ manifest.mf # other stuff nPaper-Server/target +nPaper-Server/dependency-reduced-pom.xml nPaper-API/target +nPaper-API/dependency-reduced-pom.xml +MinecraftServer/target +MinecraftServer/dependency-reduced-pom.xml diff --git a/MinecraftServer/pom.xml b/MinecraftServer/pom.xml index 3311c81b..af1f5f41 100644 --- a/MinecraftServer/pom.xml +++ b/MinecraftServer/pom.xml @@ -36,7 +36,7 @@ org.apache.maven.plugins maven-shade-plugin - 2.3 + 3.4.1 package diff --git a/nPaper-API/pom.xml b/nPaper-API/pom.xml index 3e24f577..dc0a0f96 100644 --- a/nPaper-API/pom.xml +++ b/nPaper-API/pom.xml @@ -27,7 +27,7 @@ org.jetbrains annotations - 16.0.2 + 24.0.0 net.md-5 @@ -49,7 +49,7 @@ org.yaml snakeyaml - 1.12 + 1.33 jar compile @@ -70,7 +70,7 @@ com.google.guava guava - 10.0.1 + 31.1-jre jar compile @@ -83,7 +83,7 @@ com.github.ben-manes.caffeine caffeine - 2.8.5 + 2.9.3 @@ -92,13 +92,13 @@ junit junit - 4.11 + 4.13.2 test org.hamcrest hamcrest-library - 1.3 + 2.2 test --> @@ -109,7 +109,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.10.1 1.8 1.8 @@ -118,7 +118,7 @@ org.apache.maven.plugins maven-shade-plugin - 1.4 + 3.4.1 package @@ -131,7 +131,7 @@ org.apache.maven.plugins maven-site-plugin - 3.0-beta-3 + 4.0.0-M4 @@ -142,7 +142,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.7 + 3.4.1 true diff --git a/nPaper-API/src/main/java/org/bukkit/command/defaults/DeopCommand.java b/nPaper-API/src/main/java/org/bukkit/command/defaults/DeopCommand.java index c46750a7..69bb4de4 100644 --- a/nPaper-API/src/main/java/org/bukkit/command/defaults/DeopCommand.java +++ b/nPaper-API/src/main/java/org/bukkit/command/defaults/DeopCommand.java @@ -31,6 +31,10 @@ public boolean execute(CommandSender sender, String currentAlias, String[] args) } OfflinePlayer player = Bukkit.getOfflinePlayer(args[0]); + if (!player.isOp()) { + sender.sendMessage("Player's not opped!"); + return false; + } player.setOp(false); if (player instanceof Player) { @@ -51,7 +55,7 @@ public List tabComplete(CommandSender sender, String alias, String[] arg List completions = new ArrayList(); for (OfflinePlayer player : Bukkit.getOperators()) { String playerName = player.getName(); - if (StringUtil.startsWithIgnoreCase(playerName, args[0])) { + if (StringUtil.startsWithIgnoreCase(playerName, args[0]) && player.isOp()) { completions.add(playerName); } } diff --git a/nPaper-API/src/main/java/org/bukkit/command/defaults/OpCommand.java b/nPaper-API/src/main/java/org/bukkit/command/defaults/OpCommand.java index 49a178d3..88854292 100644 --- a/nPaper-API/src/main/java/org/bukkit/command/defaults/OpCommand.java +++ b/nPaper-API/src/main/java/org/bukkit/command/defaults/OpCommand.java @@ -58,12 +58,10 @@ public List tabComplete(CommandSender sender, String alias, String[] arg return ImmutableList.of(); } - Player senderPlayer = (Player) sender; - ArrayList matchedPlayers = new ArrayList(); for (Player player : sender.getServer().getOnlinePlayers()) { String name = player.getName(); - if (!senderPlayer.canSee(player) || player.isOp()) { + if (player.isOp()) { continue; } if (StringUtil.startsWithIgnoreCase(name, lastWord)) { diff --git a/nPaper-API/src/main/java/org/bukkit/command/defaults/PardonCommand.java b/nPaper-API/src/main/java/org/bukkit/command/defaults/PardonCommand.java index bf3dacc2..41f6001b 100644 --- a/nPaper-API/src/main/java/org/bukkit/command/defaults/PardonCommand.java +++ b/nPaper-API/src/main/java/org/bukkit/command/defaults/PardonCommand.java @@ -32,6 +32,10 @@ public boolean execute(CommandSender sender, String currentAlias, String[] args) return false; } + if (!Bukkit.getBanList(BanList.Type.NAME).isBanned(args[0])) { + sender.sendMessage("Player's not banned!"); + return false; + } Bukkit.getBanList(BanList.Type.NAME).pardon(args[0]); Command.broadcastCommandMessage(sender, "Unbanned " + args[0]); return true; diff --git a/nPaper-API/src/main/java/org/bukkit/command/defaults/WhitelistCommand.java b/nPaper-API/src/main/java/org/bukkit/command/defaults/WhitelistCommand.java index 1b8078f5..5326c679 100644 --- a/nPaper-API/src/main/java/org/bukkit/command/defaults/WhitelistCommand.java +++ b/nPaper-API/src/main/java/org/bukkit/command/defaults/WhitelistCommand.java @@ -122,21 +122,13 @@ public List tabComplete(CommandSender sender, String alias, String[] arg if (args.length == 1) { return StringUtil.copyPartialMatches(args[0], WHITELIST_SUBCOMMANDS, new ArrayList(WHITELIST_SUBCOMMANDS.size())); - } else if (args.length == 2) { - if (args[0].equalsIgnoreCase("add")) { - List completions = new ArrayList(); + } + if (args.length == 2) { + if (args[0].equalsIgnoreCase("add") || args[0].equalsIgnoreCase("remove")) { + final List completions = new ArrayList(); for (OfflinePlayer player : Bukkit.getOnlinePlayers()) { // Spigot - well maybe sometimes you haven't turned the whitelist on just yet. - String name = player.getName(); - if (StringUtil.startsWithIgnoreCase(name, args[1]) && !player.isWhitelisted()) { - completions.add(name); - } - } - return completions; - } else if (args[0].equalsIgnoreCase("remove")) { - List completions = new ArrayList(); - for (OfflinePlayer player : Bukkit.getWhitelistedPlayers()) { - String name = player.getName(); - if (StringUtil.startsWithIgnoreCase(name, args[1])) { + final String name = player.getName(); + if (StringUtil.startsWithIgnoreCase(name, args[1]) && (args[0].equalsIgnoreCase("add") ? !player.isWhitelisted() : player.isWhitelisted())) { completions.add(name); } } diff --git a/nPaper-API/src/main/java/org/bukkit/entity/Player.java b/nPaper-API/src/main/java/org/bukkit/entity/Player.java index 0791c664..80a4b8e7 100644 --- a/nPaper-API/src/main/java/org/bukkit/entity/Player.java +++ b/nPaper-API/src/main/java/org/bukkit/entity/Player.java @@ -21,6 +21,9 @@ import com.sathonay.npaper.Title; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; + /** * Represents a player, connected or not */ @@ -901,6 +904,28 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline * Hide any title that is currently visible to the player */ public void hideTitle(); + + /** + * Sends an Action Bar message to the client. + * + * @param message message to display + */ + default void sendActionBar(String... message) { + BaseComponent[] messageComponents = new BaseComponent[message.length]; + int i = 0; + for (String messageLine : message) { + messageComponents[i] = new TextComponent(messageLine); + i++; + } + sendActionBar(messageComponents); + } + + /** + * Sends an Action Bar message to the client. + * + * @param message message to display + */ + void sendActionBar(BaseComponent... message); /** * Gets the Location where the player will spawn at their bed, null if diff --git a/nPaper-API/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/nPaper-API/src/main/java/org/bukkit/metadata/MetadataStoreBase.java index 093c1445..e07a3fc6 100644 --- a/nPaper-API/src/main/java/org/bukkit/metadata/MetadataStoreBase.java +++ b/nPaper-API/src/main/java/org/bukkit/metadata/MetadataStoreBase.java @@ -1,12 +1,18 @@ package org.bukkit.metadata; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; + import org.apache.commons.lang.Validate; import org.bukkit.plugin.Plugin; -import java.util.*; - public abstract class MetadataStoreBase { - private Map> metadataMap = new HashMap>(); + private Map> metadataMap = new ConcurrentHashMap>(); /** * Adds a metadata value to an object. Each metadata value is owned by a @@ -40,7 +46,9 @@ public synchronized void setMetadata(T subject, String metadataKey, MetadataValu entry = new WeakHashMap(1); metadataMap.put(key, entry); } - entry.put(owningPlugin, newMetadataValue); + synchronized (entry) { + entry.put(owningPlugin, newMetadataValue); + } } /** @@ -53,14 +61,14 @@ public synchronized void setMetadata(T subject, String metadataKey, MetadataValu * requested value. * @see MetadataStore#getMetadata(Object, String) */ - public synchronized List getMetadata(T subject, String metadataKey) { + public List getMetadata(T subject, String metadataKey) { String key = disambiguate(subject, metadataKey); - if (metadataMap.containsKey(key)) { - Collection values = metadataMap.get(key).values(); + Map entry = metadataMap.get(key); + if (entry != null) { + Collection values = entry.values(); return Collections.unmodifiableList(new ArrayList(values)); - } else { - return Collections.emptyList(); } + return Collections.emptyList(); } /** @@ -71,7 +79,7 @@ public synchronized List getMetadata(T subject, String metadataKe * @param metadataKey the unique metadata key being queried. * @return the existence of the metadataKey within subject. */ - public synchronized boolean hasMetadata(T subject, String metadataKey) { + public boolean hasMetadata(T subject, String metadataKey) { String key = disambiguate(subject, metadataKey); return metadataMap.containsKey(key); } @@ -87,7 +95,7 @@ public synchronized boolean hasMetadata(T subject, String metadataKey) { * org.bukkit.plugin.Plugin) * @throws IllegalArgumentException If plugin is null */ - public synchronized void removeMetadata(T subject, String metadataKey, Plugin owningPlugin) { + public void removeMetadata(T subject, String metadataKey, Plugin owningPlugin) { Validate.notNull(owningPlugin, "Plugin cannot be null"); String key = disambiguate(subject, metadataKey); Map entry = metadataMap.get(key); @@ -95,9 +103,11 @@ public synchronized void removeMetadata(T subject, String metadataKey, Plugin ow return; } - entry.remove(owningPlugin); - if (entry.isEmpty()) { - metadataMap.remove(key); + synchronized (entry) { + entry.remove(owningPlugin); + if (entry.isEmpty()) { + metadataMap.remove(key); + } } } @@ -110,7 +120,7 @@ public synchronized void removeMetadata(T subject, String metadataKey, Plugin ow * @see MetadataStore#invalidateAll(org.bukkit.plugin.Plugin) * @throws IllegalArgumentException If plugin is null */ - public synchronized void invalidateAll(Plugin owningPlugin) { + public void invalidateAll(Plugin owningPlugin) { Validate.notNull(owningPlugin, "Plugin cannot be null"); for (Map values : metadataMap.values()) { if (values.containsKey(owningPlugin)) { diff --git a/nPaper-API/src/main/java/org/bukkit/permissions/PermissibleBase.java b/nPaper-API/src/main/java/org/bukkit/permissions/PermissibleBase.java index 3b95061a..484975de 100644 --- a/nPaper-API/src/main/java/org/bukkit/permissions/PermissibleBase.java +++ b/nPaper-API/src/main/java/org/bukkit/permissions/PermissibleBase.java @@ -32,9 +32,8 @@ public PermissibleBase(ServerOperator opable) { public boolean isOp() { if (opable == null) { return false; - } else { - return opable.isOp(); } + return opable.isOp(); } public void setOp(boolean value) { @@ -49,7 +48,6 @@ public boolean isPermissionSet(String name) { if (name == null) { throw new IllegalArgumentException("Permission name cannot be null"); } - return permissions.containsKey(name.toLowerCase()); } @@ -57,7 +55,6 @@ public boolean isPermissionSet(Permission perm) { if (perm == null) { throw new IllegalArgumentException("Permission cannot be null"); } - return isPermissionSet(perm.getName()); } @@ -68,17 +65,16 @@ public boolean hasPermission(String inName) { String name = inName.toLowerCase(); - if (isPermissionSet(name)) { - return permissions.get(name).getValue(); - } else { - Permission perm = Bukkit.getServer().getPluginManager().getPermission(name); + PermissionAttachmentInfo info = permissions.get(name); + if (info != null) { + return info.getValue(); + } + Permission perm = Bukkit.getServer().getPluginManager().getPermission(name); - if (perm != null) { - return perm.getDefault().getValue(isOp()); - } else { - return Permission.DEFAULT_PERMISSION.getValue(isOp()); - } + if (perm != null) { + return perm.getDefault().getValue(isOp()); } + return Permission.DEFAULT_PERMISSION.getValue(isOp()); } public boolean hasPermission(Permission perm) { @@ -88,13 +84,14 @@ public boolean hasPermission(Permission perm) { String name = perm.getName().toLowerCase(); - if (isPermissionSet(name)) { - return permissions.get(name).getValue(); + PermissionAttachmentInfo info = permissions.get(name); + if (info != null) { + return info.getValue(); } return perm.getDefault().getValue(isOp()); } - public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) { + public synchronized PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) { if (name == null) { throw new IllegalArgumentException("Permission name cannot be null"); } else if (plugin == null) { @@ -111,7 +108,7 @@ public PermissionAttachment addAttachment(Plugin plugin, String name, boolean va return result; } - public PermissionAttachment addAttachment(Plugin plugin) { + public synchronized PermissionAttachment addAttachment(Plugin plugin) { if (plugin == null) { throw new IllegalArgumentException("Plugin cannot be null"); } else if (!plugin.isEnabled()) { @@ -126,7 +123,7 @@ public PermissionAttachment addAttachment(Plugin plugin) { return result; } - public void removeAttachment(PermissionAttachment attachment) { + public synchronized void removeAttachment(PermissionAttachment attachment) { if (attachment == null) { throw new IllegalArgumentException("Attachment cannot be null"); } @@ -145,7 +142,7 @@ public void removeAttachment(PermissionAttachment attachment) { } } - public void recalculatePermissions() { + public synchronized void recalculatePermissions() { clearPermissions(); Set defaults = Bukkit.getServer().getPluginManager().getDefaultPermissions(isOp()); Bukkit.getServer().getPluginManager().subscribeToDefaultPerms(isOp(), parent); @@ -192,7 +189,7 @@ private void calculateChildPermissions(Map children, boolean in } } - public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) { + public synchronized PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) { if (name == null) { throw new IllegalArgumentException("Permission name cannot be null"); } else if (plugin == null) { @@ -210,7 +207,7 @@ public PermissionAttachment addAttachment(Plugin plugin, String name, boolean va return result; } - public PermissionAttachment addAttachment(Plugin plugin, int ticks) { + public synchronized PermissionAttachment addAttachment(Plugin plugin, int ticks) { if (plugin == null) { throw new IllegalArgumentException("Plugin cannot be null"); } else if (!plugin.isEnabled()) { @@ -228,7 +225,7 @@ public PermissionAttachment addAttachment(Plugin plugin, int ticks) { } } - public Set getEffectivePermissions() { + public synchronized Set getEffectivePermissions() { return new HashSet(permissions.values()); } diff --git a/nPaper-Server/pom.xml b/nPaper-Server/pom.xml index beb381f6..b743d1d0 100644 --- a/nPaper-Server/pom.xml +++ b/nPaper-Server/pom.xml @@ -10,12 +10,11 @@ UTF-8 unknown - 4.11 + 4.13.2 1.7.10 1_7_R4 git-Bukkit- - - 2.17.2 + 2.19.0 @@ -40,6 +39,11 @@ + + io.netty + netty-all + 4.1.87.Final + org.apache.logging.log4j log4j-core @@ -80,7 +84,7 @@ net.sf.jopt-simple jopt-simple - 3.2 + 6.0-alpha-3 jar compile @@ -88,35 +92,35 @@ jline jline - 2.6 + 2.14.6 jar compile org.fusesource.jansi jansi - 1.8 + 2.4.0 jar compile org.xerial sqlite-jdbc - 3.7.2 + 3.40.0.0 jar compile mysql mysql-connector-java - 5.1.14 + 8.0.32 jar compile com.google.code.gson gson - 2.1 + 2.10.1 @@ -142,7 +146,7 @@ net.md-5 scriptus - 0.2 + 0.4.1 ex-paperspigot @@ -161,7 +165,7 @@ org.apache.maven.plugins maven-jar-plugin - 2.1 + 3.3.0 @@ -202,7 +206,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.0 + 3.4.1 package @@ -268,7 +272,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.10.1 1.8 1.8 @@ -278,7 +282,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.11 + 3.0.0-M8 ${basedir}/target/test-server @@ -290,7 +294,7 @@ --> maven-resources-plugin - 2.4.3 + 3.3.0 maps-file @@ -350,7 +354,7 @@ gitdescribe-maven-plugin - [1.3,) + 3.0 gitdescribe diff --git a/nPaper-Server/src/main/java/net/minecraft/server/Chunk.java b/nPaper-Server/src/main/java/net/minecraft/server/Chunk.java index 6331ef31..5e786574 100644 --- a/nPaper-Server/src/main/java/net/minecraft/server/Chunk.java +++ b/nPaper-Server/src/main/java/net/minecraft/server/Chunk.java @@ -29,7 +29,7 @@ public class Chunk { public final int locZ; private boolean w; public Map tileEntities; - public List[] entitySlices; + public List[] entitySlices; public boolean done; public boolean lit; public boolean m; @@ -886,7 +886,7 @@ public void removeEntities() { for (int i = 0; i < this.entitySlices.length; ++i) { // CraftBukkit start - java.util.Iterator iter = this.entitySlices[i].iterator(); + java.util.Iterator iter = this.entitySlices[i].iterator(); while (iter.hasNext()) { Entity entity = (Entity) iter.next(); // Spigot Start diff --git a/nPaper-Server/src/main/java/net/minecraft/server/ChunkProviderServer.java b/nPaper-Server/src/main/java/net/minecraft/server/ChunkProviderServer.java index 525f8d32..e35b5724 100644 --- a/nPaper-Server/src/main/java/net/minecraft/server/ChunkProviderServer.java +++ b/nPaper-Server/src/main/java/net/minecraft/server/ChunkProviderServer.java @@ -22,7 +22,7 @@ public class ChunkProviderServer implements IChunkProvider { public LongHashSet unloadQueue = new LongHashSet(); // LongHashSet public Chunk emptyChunk; public IChunkProvider chunkProvider; - private IChunkLoader f; + public IChunkLoader f; public boolean forceChunkLoad = false; // true -> false public LongObjectHashMap chunks = new LongObjectHashMap(); public WorldServer world; @@ -245,7 +245,7 @@ public Chunk loadChunk(int i, int j) { // CraftBukkit - private -> public } public void saveChunkNOP(Chunk chunk) { // CraftBukkit - private -> public - if (this.f != null) { + if (canSave() && this.f != null) { try { this.f.b(this.world, chunk); } catch (Exception exception) { @@ -255,7 +255,7 @@ public void saveChunkNOP(Chunk chunk) { // CraftBukkit - private -> public } public void saveChunk(Chunk chunk) { // CraftBukkit - private -> public - if (this.f != null) { + if (canSave() && this.f != null) { try { chunk.lastSaved = this.world.getTime(); this.f.a(this.world, chunk); @@ -338,8 +338,8 @@ public void c() { } } - public boolean unloadChunks() { - if (!this.world.savingDisabled) { + public boolean unloadChunks(boolean force) { + if (!this.world.savingDisabled && (canSave() || force)) { // CraftBukkit start Server server = this.world.getServer(); for (int i = 0; i < 100 && !this.unloadQueue.isEmpty(); i++) { @@ -385,6 +385,10 @@ public boolean unloadChunks() { return this.chunkProvider.unloadChunks(); } + + public boolean unloadChunks() { + return this.unloadChunks(false); + } public boolean canSave() { return !this.world.savingDisabled; diff --git a/nPaper-Server/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/nPaper-Server/src/main/java/net/minecraft/server/ChunkRegionLoader.java index 3b57bdb6..9788d0b6 100644 --- a/nPaper-Server/src/main/java/net/minecraft/server/ChunkRegionLoader.java +++ b/nPaper-Server/src/main/java/net/minecraft/server/ChunkRegionLoader.java @@ -17,8 +17,8 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { private java.util.LinkedHashMap pendingSaves = new java.util.LinkedHashMap(); // Spigot private static final Logger a = LogManager.getLogger(); - private List b = new ArrayList(); - private Set c = new HashSet(); + public List b = new ArrayList(); + public Set c = new HashSet(); private Object d = new Object(); private final File e; diff --git a/nPaper-Server/src/main/java/net/minecraft/server/ContainerPlayer.java b/nPaper-Server/src/main/java/net/minecraft/server/ContainerPlayer.java index 587ee261..ca725b8c 100644 --- a/nPaper-Server/src/main/java/net/minecraft/server/ContainerPlayer.java +++ b/nPaper-Server/src/main/java/net/minecraft/server/ContainerPlayer.java @@ -97,11 +97,7 @@ public ItemStack b(EntityHuman entityhuman, int i) { } slot.a(itemstack1, itemstack); - } else if (i >= 1 && i < 5) { - if (!this.a(itemstack1, 9, 45, false)) { - return null; - } - } else if (i >= 5 && i < 9) { + } else if (i >= 1 && i < 5 || i >= 5 && i < 9) { if (!this.a(itemstack1, 9, 45, false)) { return null; } diff --git a/nPaper-Server/src/main/java/net/minecraft/server/IntCache.java b/nPaper-Server/src/main/java/net/minecraft/server/IntCache.java index 47e06dfe..fea7827a 100644 --- a/nPaper-Server/src/main/java/net/minecraft/server/IntCache.java +++ b/nPaper-Server/src/main/java/net/minecraft/server/IntCache.java @@ -1,54 +1,42 @@ package net.minecraft.server; -import java.util.ArrayList; -import java.util.List; - -public class IntCache { +import java.util.ArrayDeque; +import java.util.Deque; +public final class IntCache { private static int a = 256; - private static List b = new ArrayList(); - private static List c = new ArrayList(); - private static List d = new ArrayList(); - private static List e = new ArrayList(); + private static Deque b = new ArrayDeque(); + private static Deque c = new ArrayDeque(); + private static Deque d = new ArrayDeque(); + private static Deque e = new ArrayDeque(); public static synchronized int[] a(int i) { int[] aint; if (i <= 256) { - if (b.isEmpty()) { - aint = new int[256]; - if (c.size() < org.spigotmc.SpigotConfig.intCacheLimit) c.add(aint); - return aint; - } else { - aint = (int[]) b.remove(b.size() - 1); - if (c.size() < org.spigotmc.SpigotConfig.intCacheLimit) c.add(aint); - return aint; - } - } else if (i > a) { + aint = (b.isEmpty() ? new int[256] : b.removeLast()); + if (c.size() < org.spigotmc.SpigotConfig.intCacheLimit) c.offer(aint); + return aint; + } + if (i > a) { a = i; d.clear(); e.clear(); aint = new int[a]; - if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) e.add(aint); - return aint; - } else if (d.isEmpty()) { - aint = new int[a]; - if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) e.add(aint); - return aint; - } else { - aint = (int[]) d.remove(d.size() - 1); - if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) e.add(aint); + if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) e.offer(aint); return aint; } + aint = (d.isEmpty() ? new int[a] : d.removeLast()); + if (e.size() < org.spigotmc.SpigotConfig.intCacheLimit) e.offer(aint); + return aint; } public static synchronized void a() { if (!d.isEmpty()) { - d.remove(d.size() - 1); + d.removeLast(); } - if (!b.isEmpty()) { - b.remove(b.size() - 1); + b.removeLast(); } d.addAll(e); @@ -60,4 +48,4 @@ public static synchronized void a() { public static synchronized String b() { return "cache: " + d.size() + ", tcache: " + b.size() + ", allocated: " + e.size() + ", tallocated: " + c.size(); } -} +} \ No newline at end of file diff --git a/nPaper-Server/src/main/java/net/minecraft/server/LegacyPingHandler.java b/nPaper-Server/src/main/java/net/minecraft/server/LegacyPingHandler.java new file mode 100644 index 00000000..e18e141a --- /dev/null +++ b/nPaper-Server/src/main/java/net/minecraft/server/LegacyPingHandler.java @@ -0,0 +1,191 @@ +package net.minecraft.server; + +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import net.minecraft.util.io.netty.buffer.ByteBuf; +import net.minecraft.util.io.netty.buffer.Unpooled; +import net.minecraft.util.io.netty.channel.ChannelFutureListener; +import net.minecraft.util.io.netty.channel.ChannelHandlerContext; +import net.minecraft.util.io.netty.channel.ChannelInboundHandlerAdapter; + +public class LegacyPingHandler extends ChannelInboundHandlerAdapter { + private static final Logger a = LogManager.getLogger(); + private final ServerConnection b; + private ByteBuf buf; // Paper + + public LegacyPingHandler(ServerConnection var1) { + this.b = var1; + } + + public void channelRead(ChannelHandlerContext var1, Object var2) throws Exception { + final ByteBuf var3 = (ByteBuf)var2; + // Paper start - Make legacy ping handler more reliable + if (this.buf != null) { + try { + readLegacy1_6(var1, var3); + } finally { + var3.release(); + } + return; + } + // Paper end + var3.markReaderIndex(); + boolean var4 = true; + try { + if (var3.readUnsignedByte() == 254) { + final InetSocketAddress var5 = (InetSocketAddress)var1.channel().remoteAddress(); + final MinecraftServer var6 = this.b.d(); + final int var7 = var3.readableBytes(); + String var8; + switch(var7) { + case 0: + a.debug("Ping: (<1.3.x) from {}:{}", new Object[]{var5.getAddress(), var5.getPort()}); + var8 = String.format("%s§%d§%d", var6.getMotd(), var6.C(), var6.D()); + this.a(var1, this.a(var8)); + break; + case 1: + if (var3.readUnsignedByte() != 1) { + return; + } + a.debug("Ping: (1.4-1.5.x) from {}:{}", new Object[]{var5.getAddress(), var5.getPort()}); + var8 = String.format("§1\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, var6.getVersion(), var6.getMotd(), var6.C(), var6.D()); + this.a(var1, this.a(var8)); + break; + default: + // Paper start - Replace with improved version below + if (var3.readUnsignedByte() != 0x01 || var3.readUnsignedByte() != 0xFA) return; + readLegacy1_6(var1, var3); + /* + boolean var23 = var3.readUnsignedByte() == 1; + var23 &= var3.readUnsignedByte() == 250; + var23 &= "MC|PingHost".equals(new String(var3.readBytes(var3.readShort() * 2).array(), Charsets.UTF_16BE)); + int var9 = var3.readUnsignedShort(); + var23 &= var3.readUnsignedByte() >= 73; + var23 &= 3 + var3.readBytes(var3.readShort() * 2).array().length + 4 == var9; + var23 &= var3.readInt() <= 65535; + var23 &= var3.readableBytes() == 0; + if (!var23) { + return; + } + + a.debug("Ping: (1.6) from {}:{}", new Object[]{var5.getAddress(), var5.getPort()}); + String var10 = String.format("§1\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", 127, var6.getVersion(), var6.getMotd(), var6.C(), var6.D()); + ByteBuf var11 = this.a(var10); + + try { + this.a(var1, var11); + } finally { + var11.release(); + } + */ + // Paper end + } + + var3.release(); + var4 = false; + return; + } + } catch (RuntimeException var21) { + return; + } finally { + if (var4) { + var3.resetReaderIndex(); + var1.channel().pipeline().remove("legacy_query"); + var1.fireChannelRead(var2); + } + + } + + } + + // Paper start + private static String readLegacyString(ByteBuf buf) { + final int size = buf.readShort() * Character.BYTES; + if (!buf.isReadable(size)) { + return null; + } + final String result = buf.toString(buf.readerIndex(), size, StandardCharsets.UTF_16BE); + buf.skipBytes(size); // toString doesn't increase readerIndex automatically + return result; + } + + private void readLegacy1_6(ChannelHandlerContext ctx, ByteBuf part) { + ByteBuf buf = this.buf; + if (buf == null) { + this.buf = buf = ctx.alloc().buffer(); + buf.markReaderIndex(); + } else { + buf.resetReaderIndex(); + } + buf.writeBytes(part); + if (!buf.isReadable(Short.BYTES + Short.BYTES + Byte.BYTES + Short.BYTES + Integer.BYTES)) { + return; + } + final String s = readLegacyString(buf); + if (s == null) { + return; + } + if (!s.equals("MC|PingHost")) { + removeHandler(ctx); + return; + } + if (!buf.isReadable(Short.BYTES) || !buf.isReadable(buf.readShort())) { + return; + } + final MinecraftServer server = this.b.d(); + //int protocolVersion = buf.readByte(); + final String host = readLegacyString(buf); + if (host == null) { + removeHandler(ctx); + return; + } + //int port = buf.readInt(); + if (buf.isReadable()) { + removeHandler(ctx); + return; + } + buf.release(); + this.buf = null; + a.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress()); + final String response = String.format("\u00a71\u0000%d\u0000%s\u0000%s\u0000%d\u0000%d", Byte.MAX_VALUE, server.getVersion(), server.getMotd(), server.C(), server.D()); + this.a(ctx, this.a(response)); + } + private void removeHandler(ChannelHandlerContext ctx) { + final ByteBuf buf = this.buf; + this.buf = null; + buf.resetReaderIndex(); + ctx.pipeline().remove(this); + ctx.fireChannelRead(buf); + } + @Override + public void handlerRemoved(ChannelHandlerContext ctx) { + if (this.buf != null) { + this.buf.release(); + this.buf = null; + } + } + // Paper end + + private void a(ChannelHandlerContext var1, ByteBuf var2) { + var1.pipeline().firstContext().writeAndFlush(var2).addListener(ChannelFutureListener.CLOSE); + } + + private ByteBuf a(String var1) { + final ByteBuf var2 = Unpooled.buffer(); + var2.writeByte(255); + final char[] var3 = var1.toCharArray(); + var2.writeShort(var3.length); + final char[] var4 = var3; + final int var5 = var3.length; + + for(int var6 = 0; var6 < var5; ++var6) { + final char var7 = var4[var6]; + var2.writeChar(var7); + } + return var2; + } +} \ No newline at end of file diff --git a/nPaper-Server/src/main/java/net/minecraft/server/LoginListener.java b/nPaper-Server/src/main/java/net/minecraft/server/LoginListener.java index 8be474d3..80596d6f 100644 --- a/nPaper-Server/src/main/java/net/minecraft/server/LoginListener.java +++ b/nPaper-Server/src/main/java/net/minecraft/server/LoginListener.java @@ -4,21 +4,27 @@ import java.util.Arrays; import java.util.Random; import java.util.UUID; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + import javax.crypto.SecretKey; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; + import net.minecraft.util.com.google.common.base.Charsets; import net.minecraft.util.com.mojang.authlib.GameProfile; import net.minecraft.util.com.mojang.authlib.properties.Property; import net.minecraft.util.io.netty.util.concurrent.Future; import net.minecraft.util.io.netty.util.concurrent.GenericFutureListener; import net.minecraft.util.org.apache.commons.lang3.Validate; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; public class LoginListener implements PacketLoginInListener { - private static final AtomicInteger b = new AtomicInteger(0); private static final Logger c = LogManager.getLogger(); private static final Random random = new Random(); private final byte[] e = new byte[4]; @@ -30,6 +36,14 @@ public class LoginListener implements PacketLoginInListener { private String j; private SecretKey loginKey; public String hostname = ""; // CraftBukkit - add field + + // PaperSpigot start + private static final ExecutorService POOL = new ThreadPoolExecutor(2, + Runtime.getRuntime().availableProcessors() * 2, + 60, TimeUnit.SECONDS, + new LinkedBlockingQueue<>(), + new ThreadFactoryBuilder().setNameFormat("User Authenticator #%d").build()); + // PaperSpigot end public LoginListener(MinecraftServer minecraftserver, NetworkManager networkmanager) { this.g = EnumProtocolState.HELLO; @@ -40,6 +54,10 @@ public LoginListener(MinecraftServer minecraftserver, NetworkManager networkmana } public void a() { + if (!MinecraftServer.getServer().isRunning()) { + this.disconnect(org.spigotmc.SpigotConfig.restartMessage); + return; + } if (this.g == EnumProtocolState.READY_TO_ACCEPT) { this.c(); } @@ -64,22 +82,12 @@ public void disconnect(String s) { // Spigot start public void initUUID() { - UUID uuid; - if ( networkManager.spoofedUUID != null ) - { - uuid = networkManager.spoofedUUID; - } else - { - uuid = UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + this.i.getName() ).getBytes( Charsets.UTF_8 ) ); - } + UUID uuid = (networkManager.spoofedUUID != null ? networkManager.spoofedUUID : UUID.nameUUIDFromBytes(("OfflinePlayer:" + this.i.getName()).getBytes(Charsets.UTF_8))); + this.i = new GameProfile(uuid, this.i.getName()); - this.i = new GameProfile( uuid, this.i.getName() ); - - if (networkManager.spoofedProfile != null) - { - for ( Property property : networkManager.spoofedProfile ) - { - this.i.getProperties().put( property.getName(), property ); + if (networkManager.spoofedProfile != null) { + for (Property property : networkManager.spoofedProfile) { + this.i.getProperties().put(property.getName(), property); } } } @@ -141,7 +149,8 @@ public void a(PacketLoginInStart packetlogininstart) { this.g = EnumProtocolState.KEY; this.networkManager.handle(new PacketLoginOutEncryptionBegin(this.j, this.server.K().getPublic(), this.e), new GenericFutureListener[0]); } else { - (new ThreadPlayerLookupUUID(this, "User Authenticator #" + b.incrementAndGet())).start(); // Spigot + //(new ThreadPlayerLookupUUID(this, "User Authenticator #" + b.incrementAndGet())).start(); // Spigot + POOL.execute(new ThreadPlayerLookupUUID(this)); // PaperSpigot } } @@ -155,7 +164,8 @@ public void a(PacketLoginInEncryptionBegin packetlogininencryptionbegin) { this.loginKey = packetlogininencryptionbegin.a(privatekey); this.g = EnumProtocolState.AUTHENTICATING; this.networkManager.a(this.loginKey); - (new ThreadPlayerLookupUUID(this, "User Authenticator #" + b.incrementAndGet())).start(); + //(new ThreadPlayerLookupUUID(this, "User Authenticator #" + b.incrementAndGet())).start(); + POOL.execute(new ThreadPlayerLookupUUID(this)); // PaperSpigot } } diff --git a/nPaper-Server/src/main/java/net/minecraft/server/MinecraftServer.java b/nPaper-Server/src/main/java/net/minecraft/server/MinecraftServer.java index ae23a380..bfcd5ad8 100644 --- a/nPaper-Server/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/nPaper-Server/src/main/java/net/minecraft/server/MinecraftServer.java @@ -2,6 +2,7 @@ import java.awt.GraphicsEnvironment; import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; import java.io.File; // CraftBukkit start import java.io.IOException; @@ -10,6 +11,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Base64; import java.util.Collections; import java.util.Date; import java.util.List; @@ -28,15 +30,10 @@ import jline.console.ConsoleReader; import joptsimple.OptionSet; -import net.minecraft.util.com.google.common.base.Charsets; import net.minecraft.util.com.mojang.authlib.GameProfile; import net.minecraft.util.com.mojang.authlib.GameProfileRepository; import net.minecraft.util.com.mojang.authlib.minecraft.MinecraftSessionService; import net.minecraft.util.com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -import net.minecraft.util.io.netty.buffer.ByteBuf; -import net.minecraft.util.io.netty.buffer.ByteBufOutputStream; -import net.minecraft.util.io.netty.buffer.Unpooled; -import net.minecraft.util.io.netty.handler.codec.base64.Base64; import net.minecraft.util.org.apache.commons.lang3.Validate; // CraftBukkit end @@ -438,7 +435,7 @@ public void safeShutdown() { // PaperSpigot start - Further improve tick loop private static final int TPS = 20; - private static final long SEC_IN_NANO = 1000000000; + private static final long SEC_IN_NANO = 1_000_000_000; private static final long TICK_TIME = SEC_IN_NANO / TPS; private static final long MAX_CATCHUP_BUFFER = TICK_TIME * TPS * 60L; private static final int SAMPLE_INTERVAL = 20; @@ -449,8 +446,7 @@ public void safeShutdown() { public static long START_TIME, LAST_TICK_TIME_NANO, LAST_TICK_TIME_MILLIS; public static class RollingAverage { - private final int size; - private long time; + private final int size; private double total; private int index = 0; private final double[] samples; @@ -458,7 +454,6 @@ public static class RollingAverage { RollingAverage(int size) { this.size = size; - this.time = size * SEC_IN_NANO; this.total = TPS * SEC_IN_NANO * size; this.samples = new double[size]; this.times = new long[size]; @@ -469,19 +464,19 @@ public static class RollingAverage { } public void add(double x, long t) { - time -= times[index]; - total -= samples[index]*times[index]; + index = (index + 1) % size; + total -= samples[index] * times[index]; samples[index] = x; times[index] = t; - time += t; - total += x*t; - if (++index == size) { - index = 0; - } + total += x * t; } public double getAverage() { - return total / time; + double avg = total; + for (int i = 0; i < size; i++) { + avg += samples[i] * (SEC_IN_NANO - times[i]); + } + return avg / (SEC_IN_NANO * size); } } // PaperSpigot End @@ -601,22 +596,18 @@ private void a(ServerPing serverping) { File file1 = this.d("server-icon.png"); if (file1.isFile()) { - ByteBuf bytebuf = Unpooled.buffer(); - try { - BufferedImage bufferedimage = ImageIO.read(file1); - + final BufferedImage bufferedimage = ImageIO.read(file1); Validate.validState(bufferedimage.getWidth() == bufferedimage.getHeight(), "Width must be equals to the height"); Validate.validState(bufferedimage.getWidth() == 64, "Must be 64 pixels wide"); Validate.validState(bufferedimage.getHeight() == 64, "Must be 64 pixels high"); - ImageIO.write(bufferedimage, "PNG", new ByteBufOutputStream(bytebuf)); - ByteBuf bytebuf1 = Base64.encode(bytebuf); - - serverping.setFavicon("data:image/png;base64," + bytebuf1.toString(Charsets.UTF_8)); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageIO.write(bufferedimage, "PNG", baos); + byte[] imageInByte = baos.toByteArray(); + String imageDataString = Base64.getEncoder().encodeToString(imageInByte); + serverping.setFavicon("data:image/png;base64," + imageDataString); } catch (Exception exception) { i.error("Couldn\'t load server icon", exception); - } finally { - bytebuf.release(); } } } diff --git a/nPaper-Server/src/main/java/net/minecraft/server/PlayerConnection.java b/nPaper-Server/src/main/java/net/minecraft/server/PlayerConnection.java index d8198942..821552ed 100644 --- a/nPaper-Server/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/nPaper-Server/src/main/java/net/minecraft/server/PlayerConnection.java @@ -8,8 +8,9 @@ import java.util.ArrayList; import java.util.Date; import java.util.HashSet; -import java.util.Iterator; import java.util.Random; +import java.util.Set; +import java.util.TreeSet; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; @@ -52,7 +53,6 @@ import org.github.paperspigot.PaperSpigotConfig; // PaperSpigot import net.minecraft.util.com.google.common.base.Charsets; -import net.minecraft.util.com.google.common.collect.Lists; import net.minecraft.util.io.netty.buffer.Unpooled; import net.minecraft.util.io.netty.util.concurrent.GenericFutureListener; import net.minecraft.util.org.apache.commons.lang3.StringUtils; @@ -1782,16 +1782,9 @@ public void a(PacketPlayInAbilities packetplayinabilities) { } public void a(PacketPlayInTabComplete packetplayintabcomplete) { - ArrayList arraylist = Lists.newArrayList(); - Iterator iterator = this.minecraftServer.a(this.player, packetplayintabcomplete.c()).iterator(); - - while (iterator.hasNext()) { - String s = (String) iterator.next(); - - arraylist.add(s); - } - - this.player.playerConnection.sendPacket(new PacketPlayOutTabComplete((String[]) arraylist.toArray(new String[arraylist.size()]))); + final Set hashSet = new TreeSet(this.minecraftServer.a(this.player, packetplayintabcomplete.c())); + final String[] array = hashSet.toArray(new String[hashSet.size()]); + this.player.playerConnection.sendPacket(new PacketPlayOutTabComplete(array)); } public void a(PacketPlayInSettings packetplayinsettings) { @@ -1859,10 +1852,14 @@ public void a(PacketPlayInCustomPayload packetplayincustompayload) { } if (itemstack.getItem() == Items.WRITTEN_BOOK && itemstack1.getItem() == Items.BOOK_AND_QUILL) { - itemstack1 = new ItemStack(Items.WRITTEN_BOOK); - itemstack1.a("author", (new NBTTagString(this.player.getName()))); - itemstack1.a("title", (NBTBase) (new NBTTagString(itemstack.getTag().getString("title")))); - itemstack1.a("pages", (NBTBase) itemstack.getTag().getList("pages", 8)); + itemstack1 = new ItemStack(Items.WRITTEN_BOOK); + itemstack1.a("author", (NBTBase) (new NBTTagString(this.player.getName()))); + itemstack1.a("title", (NBTBase) (new NBTTagString(itemstack.getTag().getString("title").replace("\u00A7", "")))); + NBTTagList pages = new NBTTagList(); + for (int i = 0; i < itemstack.getTag().getList("pages", 8).size(); i++) { + pages.add(new NBTTagString(itemstack.getTag().getList("pages", 8).getString(i).replace("\u00A7", ""))); + } + itemstack1.a("pages", (NBTBase) pages); itemstack1.setItem(Items.WRITTEN_BOOK); CraftEventFactory.handleEditBookEvent(player, itemstack1); // CraftBukkit } diff --git a/nPaper-Server/src/main/java/net/minecraft/server/PlayerList.java b/nPaper-Server/src/main/java/net/minecraft/server/PlayerList.java index 0da16a43..7e0dc57d 100644 --- a/nPaper-Server/src/main/java/net/minecraft/server/PlayerList.java +++ b/nPaper-Server/src/main/java/net/minecraft/server/PlayerList.java @@ -408,7 +408,7 @@ public EntityPlayer attemptLogin(LoginListener loginlistener, GameProfile gamepr } // return s; - if (!gameprofilebanentry.hasExpired()) event.disallow(PlayerLoginEvent.Result.KICK_BANNED, s); // Spigot + event.disallow(PlayerLoginEvent.Result.KICK_BANNED, s); // Spigot } else if (!this.isWhitelisted(gameprofile)) { // return "You are not white-listed on this server!"; event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, org.spigotmc.SpigotConfig.whitelistMessage); // Spigot diff --git a/nPaper-Server/src/main/java/net/minecraft/server/ThreadCommandReader.java b/nPaper-Server/src/main/java/net/minecraft/server/ThreadCommandReader.java index a5e8a45e..f1702338 100644 --- a/nPaper-Server/src/main/java/net/minecraft/server/ThreadCommandReader.java +++ b/nPaper-Server/src/main/java/net/minecraft/server/ThreadCommandReader.java @@ -1,10 +1,10 @@ package net.minecraft.server; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; +// CraftBukkit +import static org.bukkit.craftbukkit.Main.useConsole; +import static org.bukkit.craftbukkit.Main.useJline; -import static org.bukkit.craftbukkit.Main.*; // CraftBukkit +import java.io.IOException; class ThreadCommandReader extends Thread { diff --git a/nPaper-Server/src/main/java/net/minecraft/server/ThreadPlayerLookupUUID.java b/nPaper-Server/src/main/java/net/minecraft/server/ThreadPlayerLookupUUID.java index 1b2620cd..eaadc776 100644 --- a/nPaper-Server/src/main/java/net/minecraft/server/ThreadPlayerLookupUUID.java +++ b/nPaper-Server/src/main/java/net/minecraft/server/ThreadPlayerLookupUUID.java @@ -3,21 +3,19 @@ import java.math.BigInteger; import java.util.UUID; -import net.minecraft.util.com.mojang.authlib.GameProfile; -import net.minecraft.util.com.mojang.authlib.exceptions.AuthenticationUnavailableException; - // CraftBukkit start import org.bukkit.craftbukkit.util.Waitable; import org.bukkit.event.player.AsyncPlayerPreLoginEvent; import org.bukkit.event.player.PlayerPreLoginEvent; // CraftBukkit end -class ThreadPlayerLookupUUID extends Thread { +import net.minecraft.util.com.mojang.authlib.GameProfile; +import net.minecraft.util.com.mojang.authlib.exceptions.AuthenticationUnavailableException; - final LoginListener a; +class ThreadPlayerLookupUUID implements Runnable { - ThreadPlayerLookupUUID(LoginListener loginlistener, String s) { - super(s); + final LoginListener a; + ThreadPlayerLookupUUID(LoginListener loginlistener) { this.a = loginlistener; } diff --git a/nPaper-Server/src/main/java/net/minecraft/server/TileEntitySkull.java b/nPaper-Server/src/main/java/net/minecraft/server/TileEntitySkull.java index 84c7f283..95ec9004 100644 --- a/nPaper-Server/src/main/java/net/minecraft/server/TileEntitySkull.java +++ b/nPaper-Server/src/main/java/net/minecraft/server/TileEntitySkull.java @@ -139,7 +139,7 @@ private void d() { @Override public void run() { - GameProfile profile = skinCache.get( name.toLowerCase() ); // nPaper - fix skin dont show up + GameProfile profile = skinCache.getIfPresent( name.toLowerCase() ); // nPaper - fix skin dont show up if (profile != null) { final GameProfile finalProfile = profile; diff --git a/nPaper-Server/src/main/java/net/minecraft/server/World.java b/nPaper-Server/src/main/java/net/minecraft/server/World.java index 141c6a91..f53a1f2d 100644 --- a/nPaper-Server/src/main/java/net/minecraft/server/World.java +++ b/nPaper-Server/src/main/java/net/minecraft/server/World.java @@ -882,13 +882,13 @@ public MovingObjectPosition rayTrace(Vec3D vec3d, Vec3D vec3d1, boolean flag) { public MovingObjectPosition rayTrace(Vec3D vec3d, Vec3D vec3d1, boolean flag, boolean flag1, boolean flag2) { if (!Double.isNaN(vec3d.a) && !Double.isNaN(vec3d.b) && !Double.isNaN(vec3d.c)) { if (!Double.isNaN(vec3d1.a) && !Double.isNaN(vec3d1.b) && !Double.isNaN(vec3d1.c)) { - int i = MathHelper.floor(vec3d1.a); - int j = MathHelper.floor(vec3d1.b); - int k = MathHelper.floor(vec3d1.c); + final int i = MathHelper.floor(vec3d1.a); + final int j = MathHelper.floor(vec3d1.b); + final int k = MathHelper.floor(vec3d1.c); int l = MathHelper.floor(vec3d.a); int i1 = MathHelper.floor(vec3d.b); int j1 = MathHelper.floor(vec3d.c); - Block block = this.getType(l, i1, j1); + final Block block = this.getType(l, i1, j1); int k1 = this.getData(l, i1, j1); if ((!flag1 || block.a(this, l, i1, j1) != null) && block.a(k1, flag)) { @@ -915,7 +915,7 @@ public MovingObjectPosition rayTrace(Vec3D vec3d, Vec3D vec3d1, boolean flag, bo boolean flag3 = true; boolean flag4 = true; boolean flag5 = true; - double d0 = 999.0D; + /*double d0 = 999.0D; double d1 = 999.0D; double d2 = 999.0D; @@ -941,14 +941,28 @@ public MovingObjectPosition rayTrace(Vec3D vec3d, Vec3D vec3d1, boolean flag, bo d2 = (double) j1 + 0.0D; } else { flag5 = false; + }*/ + // Rinny start - optimize rayTrace + final double d0 = i > l ? l + 1.0 : (i < l ? l : l + 0.0); + final double d1 = j > i1 ? i1 + 1.0 : (j < i1 ? i1 : i1 + 0.0); + final double d2 = k > j1 ? j1 + 1.0 : (k < j1 ? j1 : j1 + 0.0); + + if (i == l) { + flag3 = false; + } + if (j == i1) { + flag4 = false; + } + if (k == j1) { + flag5 = false; } double d3 = 999.0D; double d4 = 999.0D; double d5 = 999.0D; - double d6 = vec3d1.a - vec3d.a; - double d7 = vec3d1.b - vec3d.b; - double d8 = vec3d1.c - vec3d.c; + final double d6 = vec3d1.a - vec3d.a; + final double d7 = vec3d1.b - vec3d.b; + final double d8 = vec3d1.c - vec3d.c; if (flag3) { d3 = (d0 - vec3d.a) / d6; @@ -961,8 +975,14 @@ public MovingObjectPosition rayTrace(Vec3D vec3d, Vec3D vec3d1, boolean flag, bo if (flag5) { d5 = (d2 - vec3d.c) / d8; } + + // Avoid calculating useless stuff + if (block.a(this, l, i1, j1, vec3d, vec3d1) == null) { + continue; + } + // Rinny end - boolean flag6 = false; + //boolean flag6 = false; byte b0; if (d3 < d4 && d3 < d5) { @@ -997,7 +1017,7 @@ public MovingObjectPosition rayTrace(Vec3D vec3d, Vec3D vec3d1, boolean flag, bo vec3d.c = d2; } - Vec3D vec3d2 = Vec3D.a(vec3d.a, vec3d.b, vec3d.c); + final Vec3D vec3d2 = Vec3D.a(vec3d.a, vec3d.b, vec3d.c); l = (int) (vec3d2.a = (double) MathHelper.floor(vec3d.a)); if (b0 == 5) { @@ -1017,8 +1037,8 @@ public MovingObjectPosition rayTrace(Vec3D vec3d, Vec3D vec3d1, boolean flag, bo ++vec3d2.c; } - Block block1 = this.getType(l, i1, j1); - int l1 = this.getData(l, i1, j1); + final Block block1 = this.getType(l, i1, j1); + final int l1 = this.getData(l, i1, j1); if (!flag1 || block1.a(this, l, i1, j1) != null) { if (block1.a(l1, flag)) { diff --git a/nPaper-Server/src/main/java/net/minecraft/server/WorldServer.java b/nPaper-Server/src/main/java/net/minecraft/server/WorldServer.java index 3fc108ee..82ae9290 100644 --- a/nPaper-Server/src/main/java/net/minecraft/server/WorldServer.java +++ b/nPaper-Server/src/main/java/net/minecraft/server/WorldServer.java @@ -189,7 +189,10 @@ public void doTick() { // CraftBukkit end timings.doChunkUnload.startTiming(); // Spigot this.methodProfiler.c("chunkSource"); - this.chunkProvider.unloadChunks(); + // Only unload if chunkProvider isn't null + if (this.chunkProvider != null) { + this.chunkProvider.unloadChunks(); + } int j = this.a(1.0F); if (j != this.j) { diff --git a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/CraftChunk.java index 99d3d40f..48790780 100644 --- a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/CraftChunk.java +++ b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/CraftChunk.java @@ -1,22 +1,25 @@ package org.bukkit.craftbukkit; import java.lang.ref.WeakReference; +import java.util.ArrayList; import java.util.Arrays; - -import net.minecraft.server.BiomeBase; -import net.minecraft.server.ChunkPosition; -import net.minecraft.server.ChunkSection; -import net.minecraft.server.EmptyChunk; -import net.minecraft.server.WorldChunkManager; -import net.minecraft.server.WorldServer; +import java.util.Iterator; +import java.util.List; import org.bukkit.Chunk; +import org.bukkit.ChunkSnapshot; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockState; import org.bukkit.craftbukkit.block.CraftBlock; import org.bukkit.entity.Entity; -import org.bukkit.ChunkSnapshot; + +import net.minecraft.server.BiomeBase; +import net.minecraft.server.ChunkPosition; +import net.minecraft.server.ChunkSection; +import net.minecraft.server.EmptyChunk; +import net.minecraft.server.WorldChunkManager; +import net.minecraft.server.WorldServer; public class CraftChunk implements Chunk { private WeakReference weakChunk; @@ -81,42 +84,31 @@ public Block getBlock(int x, int y, int z) { } public Entity[] getEntities() { - int count = 0, index = 0; - net.minecraft.server.Chunk chunk = getHandle(); - - for (int i = 0; i < 16; i++) { - count += chunk.entitySlices[i].size(); - } - - Entity[] entities = new Entity[count]; - - for (int i = 0; i < 16; i++) { - for (Object obj : chunk.entitySlices[i].toArray()) { - if (!(obj instanceof net.minecraft.server.Entity)) { - continue; - } - - entities[index++] = ((net.minecraft.server.Entity) obj).getBukkitEntity(); - } - } - - return entities; + // Rinny start + List entities = new ArrayList<>(); + net.minecraft.server.Chunk chunk = getHandle(); + for (int i = 0; i < 16; i++) { + for (net.minecraft.server.Entity entity : chunk.entitySlices[i]) { + if (entity != null) { + entities.add(entity.getBukkitEntity()); + } + } + } + return entities.toArray(new Entity[0]); + // Rinny end } public BlockState[] getTileEntities() { - int index = 0; - net.minecraft.server.Chunk chunk = getHandle(); - BlockState[] entities = new BlockState[chunk.tileEntities.size()]; - - for (Object obj : chunk.tileEntities.keySet().toArray()) { - if (!(obj instanceof ChunkPosition)) { - continue; - } - - ChunkPosition position = (ChunkPosition) obj; - entities[index++] = worldServer.getWorld().getBlockAt(position.x + (chunk.locX << 4), position.y, position.z + (chunk.locZ << 4)).getState(); - } - return entities; + // Rinny start + net.minecraft.server.Chunk chunk = getHandle(); + List entities = new ArrayList(chunk.tileEntities.size()); + Iterator iterator = chunk.tileEntities.keySet().iterator(); + while (iterator.hasNext()){ + ChunkPosition position = iterator.next(); + entities.add(worldServer.getWorld().getBlockAt(position.x + (chunk.locX << 4), position.y, position.z + (chunk.locZ << 4)).getState()); + } + return entities.toArray(new BlockState[entities.size()]); + // Rinny end } public boolean isLoaded() { @@ -147,7 +139,8 @@ public ChunkSnapshot getChunkSnapshot() { return getChunkSnapshot(true, false, false); } - public ChunkSnapshot getChunkSnapshot(boolean includeMaxBlockY, boolean includeBiome, boolean includeBiomeTempRain) { + // BUKKIT VERSION - OLD + /*public ChunkSnapshot getChunkSnapshot(boolean includeMaxBlockY, boolean includeBiome, boolean includeBiomeTempRain) { net.minecraft.server.Chunk chunk = getHandle(); ChunkSection[] cs = chunk.getSections(); @@ -158,22 +151,22 @@ public ChunkSnapshot getChunkSnapshot(boolean includeMaxBlockY, boolean includeB boolean[] sectionEmpty = new boolean[cs.length]; for (int i = 0; i < cs.length; i++) { - if (cs[i] == null) { /* Section is empty? */ + if (cs[i] == null) { sectionBlockIDs[i] = emptyBlockIDs; sectionBlockData[i] = emptyData; sectionSkyLights[i] = emptySkyLight; sectionEmitLights[i] = emptyData; sectionEmpty[i] = true; - } else { /* Not empty */ + } else { short[] blockids = new short[4096]; byte[] baseids = cs[i].getIdArray(); - /* Copy base IDs */ + for (int j = 0; j < 4096; j++) { blockids[j] = (short) (baseids[j] & 0xFF); } - if (cs[i].getExtendedIdArray() != null) { /* If we've got extended IDs */ + if (cs[i].getExtendedIdArray() != null) { byte[] extids = cs[i].getExtendedIdArray().a; for (int j = 0; j < 2048; j++) { @@ -190,7 +183,7 @@ public ChunkSnapshot getChunkSnapshot(boolean includeMaxBlockY, boolean includeB sectionBlockIDs[i] = blockids; - /* Get block data nibbles */ + sectionBlockData[i] = new byte[2048]; System.arraycopy(cs[i].getDataArray().a, 0, sectionBlockData[i], 0, 2048); if (cs[i].getSkyLightArray() == null) { @@ -244,10 +237,94 @@ public ChunkSnapshot getChunkSnapshot(boolean includeMaxBlockY, boolean includeB World world = getWorld(); return new CraftChunkSnapshot(getX(), getZ(), world.getName(), world.getFullTime(), sectionBlockIDs, sectionBlockData, sectionSkyLights, sectionEmitLights, sectionEmpty, hmap, biome, biomeTemp, biomeRain); + }*/ + + // Rinny version - NEW + public ChunkSnapshot getChunkSnapshot(boolean includeMaxBlockY, boolean includeBiome, boolean includeBiomeTempRain) { + net.minecraft.server.Chunk chunk = getHandle(); + ChunkSection[] cs = chunk.getSections(); + short[][] sectionBlockIDs = new short[cs.length][]; + byte[][] sectionBlockData = new byte[cs.length][]; + byte[][] sectionSkyLights = new byte[cs.length][]; + byte[][] sectionEmitLights = new byte[cs.length][]; + boolean[] sectionEmpty = new boolean[cs.length]; + + for (int i = 0; i < cs.length; i++) { + if (cs[i] == null) { /* Section is empty? */ + sectionBlockIDs[i] = emptyBlockIDs; + sectionBlockData[i] = emptyData; + sectionSkyLights[i] = emptySkyLight; + sectionEmitLights[i] = emptyData; + sectionEmpty[i] = true; + } else { /* Not empty */ + short[] blockids = new short[4096]; + byte[] baseids = cs[i].getIdArray(); + + /* Copy base IDs */ + for (int j = 0; j < 4096; j++) { + blockids[j] = (short) (baseids[j] & 0xFF); + } + + if (cs[i].getExtendedIdArray() != null) { /* If we've got extended IDs */ + byte[] extids = cs[i].getExtendedIdArray().a; + + for (int j = 0; j < 2048; j++) { + short b = (short) (extids[j] & 0xFF); + + if (b == 0) { + continue; + } + + blockids[j << 1] |= (b & 0x0F) << 8; + blockids[(j << 1) + 1] |= (b & 0xF0) << 4; + } + } + + sectionBlockIDs[i] = blockids; + sectionBlockData[i] = cs[i].getDataArray().a; + sectionSkyLights[i] = cs[i].getSkyLightArray() != null ? cs[i].getSkyLightArray().a : emptyData; + sectionEmitLights[i] = cs[i].getEmittedLightArray().a; + } + } + + int[] hmap = includeMaxBlockY ? chunk.heightMap.clone() : null; + + BiomeBase[] biome = null; + double[] biomeTemp = null; + double[] biomeRain = null; + + if (includeBiome || includeBiomeTempRain) { + WorldChunkManager wcm = chunk.world.getWorldChunkManager(); + + if (includeBiome) { + biome = new BiomeBase[256]; + for (int i = 0; i < 256; i++) { + biome[i] = chunk.getBiome(i & 0xF, i >> 4, wcm); + } + } + + if (includeBiomeTempRain) { + biomeTemp = new double[256]; + biomeRain = new double[256]; + float[] dat = getTemperatures(wcm, getX() << 4, getZ() << 4); + + for (int i = 0; i < 256; i++) { + biomeTemp[i] = dat[i]; + } + + dat = wcm.getWetness(null, getX() << 4, getZ() << 4, 16, 16); + + for (int i = 0; i < 256; i++) { + biomeRain[i] = dat[i]; + } + } + } + return new CraftChunkSnapshot(getX(), getZ(), getWorld().getName(), getWorld().getFullTime(), sectionBlockIDs, sectionBlockData, sectionSkyLights, sectionEmitLights, sectionEmpty, hmap, biome, biomeTemp, biomeRain); } public static ChunkSnapshot getEmptyChunkSnapshot(int x, int z, CraftWorld world, boolean includeBiome, boolean includeBiomeTempRain) { - BiomeBase[] biome = null; + // Rinny start + BiomeBase[] biome = null; double[] biomeTemp = null; double[] biomeRain = null; @@ -286,15 +363,14 @@ public static ChunkSnapshot getEmptyChunkSnapshot(int x, int z, CraftWorld world byte[][] blockData = new byte[hSection][]; boolean[] empty = new boolean[hSection]; - for (int i = 0; i < hSection; i++) { - blockIDs[i] = emptyBlockIDs; - skyLight[i] = emptySkyLight; - emitLight[i] = emptyData; - blockData[i] = emptyData; - empty[i] = true; - } - - return new CraftChunkSnapshot(x, z, world.getName(), world.getFullTime(), blockIDs, blockData, skyLight, emitLight, empty, new int[256], biome, biomeTemp, biomeRain); + Arrays.fill(empty, true); + Arrays.fill(blockIDs, emptyBlockIDs); + Arrays.fill(skyLight, emptySkyLight); + Arrays.fill(emitLight, emptyData); + Arrays.fill(blockData, emptyData); + int[] hmap = new int[256]; + return new CraftChunkSnapshot(x, z, world.getName(), world.getFullTime(), blockIDs, blockData, skyLight, emitLight, empty, hmap, biome, biomeTemp, biomeRain); + // Rinny end } private static float[] getTemperatures(WorldChunkManager chunkmanager, int chunkX, int chunkZ) { diff --git a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/CraftProfileBanList.java b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/CraftProfileBanList.java index fad6a965..3c3664bf 100644 --- a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/CraftProfileBanList.java +++ b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/CraftProfileBanList.java @@ -91,6 +91,9 @@ public void pardon(String target) { Validate.notNull(target, "Target cannot be null"); GameProfile profile = MinecraftServer.getServer().getUserCache().getProfile(target); + if (profile == null) { + return; + } list.remove(profile); } } diff --git a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 970bdc23..837f97c2 100644 --- a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -1,6 +1,7 @@ package org.bukkit.craftbukkit; import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -8,6 +9,7 @@ import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; +import java.util.Base64; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; @@ -23,86 +25,7 @@ import javax.imageio.ImageIO; -import net.minecraft.server.ChunkCoordinates; -import net.minecraft.server.CommandAchievement; -import net.minecraft.server.CommandBan; -import net.minecraft.server.CommandBanIp; -import net.minecraft.server.CommandBanList; -import net.minecraft.server.CommandClear; -import net.minecraft.server.CommandDeop; -import net.minecraft.server.CommandDifficulty; -import net.minecraft.server.CommandEffect; -import net.minecraft.server.CommandEnchant; -import net.minecraft.server.CommandGamemode; -import net.minecraft.server.CommandGamemodeDefault; -import net.minecraft.server.CommandGamerule; -import net.minecraft.server.CommandGive; -import net.minecraft.server.CommandHelp; -import net.minecraft.server.CommandIdleTimeout; -import net.minecraft.server.CommandKick; -import net.minecraft.server.CommandKill; -import net.minecraft.server.CommandList; -import net.minecraft.server.CommandMe; -import net.minecraft.server.CommandNetstat; -import net.minecraft.server.CommandOp; -import net.minecraft.server.CommandPardon; -import net.minecraft.server.CommandPardonIP; -import net.minecraft.server.CommandPlaySound; -import net.minecraft.server.CommandSay; -import net.minecraft.server.CommandScoreboard; -import net.minecraft.server.CommandSeed; -import net.minecraft.server.CommandSetBlock; -import net.minecraft.server.CommandSetWorldSpawn; -import net.minecraft.server.CommandSpawnpoint; -import net.minecraft.server.CommandSpreadPlayers; -import net.minecraft.server.CommandSummon; -import net.minecraft.server.CommandTell; -import net.minecraft.server.CommandTellRaw; -import net.minecraft.server.CommandTestFor; -import net.minecraft.server.CommandTestForBlock; -import net.minecraft.server.CommandTime; -import net.minecraft.server.CommandToggleDownfall; -import net.minecraft.server.CommandTp; -import net.minecraft.server.CommandWeather; -import net.minecraft.server.CommandWhitelist; -import net.minecraft.server.CommandXp; -import net.minecraft.server.Convertable; -import net.minecraft.server.ConvertProgressUpdater; -import net.minecraft.server.CraftingManager; -import net.minecraft.server.DedicatedPlayerList; -import net.minecraft.server.DedicatedServer; -import net.minecraft.server.Enchantment; -import net.minecraft.server.EntityPlayer; -import net.minecraft.server.EntityTracker; -import net.minecraft.server.EnumDifficulty; -import net.minecraft.server.EnumGamemode; -import net.minecraft.server.ExceptionWorldConflict; -import net.minecraft.server.Items; -import net.minecraft.server.JsonListEntry; -import net.minecraft.server.PlayerList; -import net.minecraft.server.RecipesFurnace; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.MobEffectList; -import net.minecraft.server.PropertyManager; -import net.minecraft.server.ServerCommand; -import net.minecraft.server.RegionFile; -import net.minecraft.server.RegionFileCache; -import net.minecraft.server.ServerNBTManager; -import net.minecraft.server.WorldLoaderServer; -import net.minecraft.server.WorldManager; -import net.minecraft.server.WorldMap; -import net.minecraft.server.PersistentCollection; -import net.minecraft.server.WorldNBTStorage; -import net.minecraft.server.WorldServer; -import net.minecraft.server.WorldSettings; -import net.minecraft.server.WorldType; -import net.minecraft.util.com.google.common.base.Charsets; -import net.minecraft.util.com.mojang.authlib.GameProfile; -import net.minecraft.util.io.netty.buffer.ByteBuf; -import net.minecraft.util.io.netty.buffer.ByteBufOutputStream; -import net.minecraft.util.io.netty.buffer.Unpooled; -import net.minecraft.util.io.netty.handler.codec.base64.Base64; - +import org.apache.commons.lang.Validate; import org.bukkit.BanList; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -120,7 +43,6 @@ import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.PluginCommand; import org.bukkit.command.SimpleCommandMap; -import org.bukkit.command.defaults.VanillaCommand; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.serialization.ConfigurationSerialization; @@ -158,9 +80,9 @@ import org.bukkit.generator.ChunkGenerator; import org.bukkit.help.HelpMap; import org.bukkit.inventory.FurnaceRecipe; -import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.Recipe; import org.bukkit.inventory.ShapedRecipe; import org.bukkit.inventory.ShapelessRecipe; @@ -174,25 +96,102 @@ import org.bukkit.plugin.SimpleServicesManager; import org.bukkit.plugin.java.JavaPluginLoader; import org.bukkit.plugin.messaging.Messenger; +import org.bukkit.plugin.messaging.StandardMessenger; import org.bukkit.potion.Potion; import org.bukkit.potion.PotionEffectType; -import org.bukkit.plugin.messaging.StandardMessenger; import org.bukkit.scheduler.BukkitWorker; import org.bukkit.util.StringUtil; import org.bukkit.util.permissions.DefaultPermissions; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.SafeConstructor; import org.yaml.snakeyaml.error.MarkedYAMLException; -import org.apache.commons.lang.Validate; import com.avaje.ebean.config.DataSourceConfig; import com.avaje.ebean.config.ServerConfig; import com.avaje.ebean.config.dbplatform.SQLitePlatform; import com.avaje.ebeaninternal.server.lib.sql.TransactionIsolation; import com.google.common.collect.ImmutableList; -import com.google.common.collect.MapMaker; +import com.google.common.cache.CacheBuilder; import jline.console.ConsoleReader; +import net.minecraft.server.ChunkCoordinates; +import net.minecraft.server.ChunkProviderServer; +import net.minecraft.server.ChunkRegionLoader; +import net.minecraft.server.CommandAchievement; +import net.minecraft.server.CommandBan; +import net.minecraft.server.CommandBanIp; +import net.minecraft.server.CommandBanList; +import net.minecraft.server.CommandClear; +import net.minecraft.server.CommandDeop; +import net.minecraft.server.CommandDifficulty; +import net.minecraft.server.CommandEffect; +import net.minecraft.server.CommandEnchant; +import net.minecraft.server.CommandGamemode; +import net.minecraft.server.CommandGamemodeDefault; +import net.minecraft.server.CommandGamerule; +import net.minecraft.server.CommandGive; +import net.minecraft.server.CommandHelp; +import net.minecraft.server.CommandIdleTimeout; +import net.minecraft.server.CommandKick; +import net.minecraft.server.CommandKill; +import net.minecraft.server.CommandList; +import net.minecraft.server.CommandMe; +import net.minecraft.server.CommandNetstat; +import net.minecraft.server.CommandOp; +import net.minecraft.server.CommandPardon; +import net.minecraft.server.CommandPardonIP; +import net.minecraft.server.CommandPlaySound; +import net.minecraft.server.CommandSay; +import net.minecraft.server.CommandScoreboard; +import net.minecraft.server.CommandSeed; +import net.minecraft.server.CommandSetBlock; +import net.minecraft.server.CommandSetWorldSpawn; +import net.minecraft.server.CommandSpawnpoint; +import net.minecraft.server.CommandSpreadPlayers; +import net.minecraft.server.CommandSummon; +import net.minecraft.server.CommandTell; +import net.minecraft.server.CommandTellRaw; +import net.minecraft.server.CommandTestFor; +import net.minecraft.server.CommandTestForBlock; +import net.minecraft.server.CommandTime; +import net.minecraft.server.CommandToggleDownfall; +import net.minecraft.server.CommandTp; +import net.minecraft.server.CommandWeather; +import net.minecraft.server.CommandWhitelist; +import net.minecraft.server.CommandXp; +import net.minecraft.server.ConvertProgressUpdater; +import net.minecraft.server.Convertable; +import net.minecraft.server.CraftingManager; +import net.minecraft.server.DedicatedPlayerList; +import net.minecraft.server.DedicatedServer; +import net.minecraft.server.Enchantment; +import net.minecraft.server.EntityPlayer; +import net.minecraft.server.EntityTracker; +import net.minecraft.server.EnumDifficulty; +import net.minecraft.server.EnumGamemode; +import net.minecraft.server.ExceptionWorldConflict; +import net.minecraft.server.FileIOThread; +import net.minecraft.server.Items; +import net.minecraft.server.JsonListEntry; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.MobEffectList; +import net.minecraft.server.PersistentCollection; +import net.minecraft.server.PlayerList; +import net.minecraft.server.PropertyManager; +import net.minecraft.server.RecipesFurnace; +import net.minecraft.server.RegionFile; +import net.minecraft.server.RegionFileCache; +import net.minecraft.server.ServerCommand; +import net.minecraft.server.ServerNBTManager; +import net.minecraft.server.WorldLoaderServer; +import net.minecraft.server.WorldManager; +import net.minecraft.server.WorldMap; +import net.minecraft.server.WorldNBTStorage; +import net.minecraft.server.WorldServer; +import net.minecraft.server.WorldSettings; +import net.minecraft.server.WorldType; +import net.minecraft.util.com.google.common.base.Charsets; +import net.minecraft.util.com.mojang.authlib.GameProfile; public final class CraftServer implements Server { private static final Player[] EMPTY_PLAYER_ARRAY = new Player[0]; @@ -213,7 +212,7 @@ public final class CraftServer implements Server { private YamlConfiguration configuration; private YamlConfiguration commandsConfiguration; private final Yaml yaml = new Yaml(new SafeConstructor()); - private final Map offlinePlayers = new MapMaker().softValues().makeMap(); + private final Map offlinePlayers = CacheBuilder.newBuilder().softValues().build().asMap(); private final AutoUpdater updater; private final EntityMetadataStore entityMetadata = new EntityMetadataStore(); private final PlayerMetadataStore playerMetadata = new PlayerMetadataStore(); @@ -692,9 +691,8 @@ public long getConnectionThrottle() { // Spigot Start - Automatically set connection throttle for bungee configurations if (org.spigotmc.SpigotConfig.bungee) { return -1; - } else { - return this.configuration.getInt("settings.connection-throttle"); } + return this.configuration.getInt("settings.connection-throttle"); // Spigot End } @@ -948,23 +946,20 @@ public World createWorld(WorldCreator creator) { Validate.notNull(creator, "Creator may not be null"); String name = creator.name(); - ChunkGenerator generator = creator.generator(); - File folder = new File(getWorldContainer(), name); World world = getWorld(name); - WorldType type = WorldType.getType(creator.type().getName()); - boolean generateStructures = creator.generateStructures(); - if (world != null) { return world; } - + File folder = new File(getWorldContainer(), name); if ((folder.exists()) && (!folder.isDirectory())) { throw new IllegalArgumentException("File exists with the name '" + name + "' and isn't a folder"); } - + ChunkGenerator generator = creator.generator(); if (generator == null) { generator = getGenerator(name); } + WorldType type = WorldType.getType(creator.type().getName()); + boolean generateStructures = creator.generateStructures(); Convertable converter = new WorldLoaderServer(getWorldContainer()); if (converter.isConvertable(name)) { @@ -1065,6 +1060,10 @@ public boolean unloadWorld(World world, boolean save) { if (e.isCancelled()) { return false; } + + worlds.remove(world.getName().toLowerCase()); + worldIdentifier.remove(world.getUID()); + console.worlds.remove(console.worlds.indexOf(handle)); if (save) { try { @@ -1075,12 +1074,20 @@ public boolean unloadWorld(World world, boolean save) { } catch (ExceptionWorldConflict ex) { getLogger().log(Level.SEVERE, null, ex); } + } else { // FlamePaper - Fix chunk memory leak + ChunkProviderServer chunkProviderServer = handle.chunkProviderServer; + ChunkRegionLoader regionLoader = (ChunkRegionLoader) chunkProviderServer.f; + + regionLoader.b.clear(); + regionLoader.c.clear(); + + FileIOThread.a.a(); + chunkProviderServer.unloadChunks(true); + chunkProviderServer.f = null; + chunkProviderServer.chunkProvider = null; + chunkProviderServer.chunks.clear(); } - worlds.remove(world.getName().toLowerCase()); - worldIdentifier.remove(world.getUID()); - console.worlds.remove(console.worlds.indexOf(handle)); - File parentFolder = world.getWorldFolder().getAbsoluteFile(); // Synchronized because access to RegionFileCache.a is guarded by this lock. @@ -1797,14 +1804,16 @@ public CraftIconCache loadServerIcon(BufferedImage image) throws Exception { } static CraftIconCache loadServerIcon0(BufferedImage image) throws Exception { - ByteBuf bytebuf = Unpooled.buffer(); - + Validate.isTrue(image.getWidth() == image.getHeight(), "Width must be equals to the height"); Validate.isTrue(image.getWidth() == 64, "Must be 64 pixels wide"); Validate.isTrue(image.getHeight() == 64, "Must be 64 pixels high"); - ImageIO.write(image, "PNG", new ByteBufOutputStream(bytebuf)); - ByteBuf bytebuf1 = Base64.encode(bytebuf); - return new CraftIconCache("data:image/png;base64," + bytebuf1.toString(Charsets.UTF_8)); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageIO.write(image, "PNG", baos); + byte[] imageInByte = baos.toByteArray(); + String imageDataString = Base64.getEncoder().encodeToString(imageInByte); + + return new CraftIconCache("data:image/png;base64," + imageDataString); } @Override diff --git a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java index b339cf3e..e2f6d98f 100644 --- a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java +++ b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/command/ServerCommandSender.java @@ -1,5 +1,7 @@ package org.bukkit.craftbukkit.command; +import java.util.Set; + import org.bukkit.Bukkit; import org.bukkit.Server; import org.bukkit.command.CommandSender; @@ -9,21 +11,22 @@ import org.bukkit.permissions.PermissionAttachmentInfo; import org.bukkit.plugin.Plugin; -import java.util.Set; - public abstract class ServerCommandSender implements CommandSender { - private static PermissibleBase blockPermInst; + //private static PermissibleBase blockPermInst; // Rinny - fix mem leak private final PermissibleBase perm; public ServerCommandSender() { - if (this instanceof CraftBlockCommandSender) { + // Rinny start - FIX MEM LEAK + /*if (this instanceof CraftBlockCommandSender) { if (blockPermInst == null) { blockPermInst = new PermissibleBase(this); } this.perm = blockPermInst; } else { this.perm = new PermissibleBase(this); - } + }*/ + this.perm = new PermissibleBase(this); + // Rinny end } public boolean isPermissionSet(String name) { diff --git a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/conversations/ConversationTracker.java b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/conversations/ConversationTracker.java index 30ef7d9a..a1bca06c 100644 --- a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/conversations/ConversationTracker.java +++ b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/conversations/ConversationTracker.java @@ -41,16 +41,16 @@ public synchronized void abandonConversation(Conversation conversation, Conversa } public synchronized void abandonAllConversations() { - - LinkedList oldQueue = conversationQueue; - conversationQueue = new LinkedList(); - for (Conversation conversation : oldQueue) { + // Rinny + for (Conversation conversation : conversationQueue) { try { conversation.abandon(new ConversationAbandonedEvent(conversation, new ManuallyAbandonedConversationCanceller())); } catch (Throwable t) { Bukkit.getLogger().log(Level.SEVERE, "Unexpected exception while abandoning a conversation", t); } } + conversationQueue.clear(); + // Rinny } public synchronized void acceptConversationInput(String input) { diff --git a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 14fac3ed..07b2fccb 100644 --- a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -291,6 +291,17 @@ public void hideTitle() { getHandle().playerConnection.sendPacket(new PacketTitle(EnumTitleAction.CLEAR, (BaseComponent[]) null, 0, 0, 0)); } // Paper end + + @Override + public void sendActionBar(BaseComponent... message) { + if(getHandle().playerConnection == null) return; + if (getHandle().playerConnection.networkManager.getVersion() < 28) { + return; + } + PacketPlayOutChat packet = new PacketPlayOutChat(null, (byte) 2); + packet.components = message; + getHandle().playerConnection.sendPacket(packet); + } @Override public int getPing() { diff --git a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/inventory/CraftFurnaceRecipe.java b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/inventory/CraftFurnaceRecipe.java index 69f17db8..185168aa 100644 --- a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/inventory/CraftFurnaceRecipe.java +++ b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/inventory/CraftFurnaceRecipe.java @@ -1,11 +1,10 @@ package org.bukkit.craftbukkit.inventory; -import net.minecraft.server.RecipesFurnace; - -import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.inventory.FurnaceRecipe; import org.bukkit.inventory.ItemStack; +import net.minecraft.server.RecipesFurnace; + public class CraftFurnaceRecipe extends FurnaceRecipe implements CraftRecipe { public CraftFurnaceRecipe(ItemStack result, ItemStack source) { super(result, source.getType(), source.getDurability()); diff --git a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java index 46a1d387..081a901a 100644 --- a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java +++ b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryAnvil.java @@ -23,13 +23,8 @@ public IInventory getIngredientsInventory() { @Override public ItemStack getItem(int slot) { - if (slot < getIngredientsInventory().getSize()) { - net.minecraft.server.ItemStack item = getIngredientsInventory().getItem(slot); - return item == null ? null : CraftItemStack.asCraftMirror(item); - } else { - net.minecraft.server.ItemStack item = getResultInventory().getItem(slot - getIngredientsInventory().getSize()); - return item == null ? null : CraftItemStack.asCraftMirror(item); - } + net.minecraft.server.ItemStack item = (slot < getIngredientsInventory().getSize() ? getIngredientsInventory().getItem(slot) : getResultInventory().getItem(slot - getIngredientsInventory().getSize())); + return item == null ? null : CraftItemStack.asCraftMirror(item); } @Override diff --git a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCrafting.java b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCrafting.java index 7bbf1df5..a15531dd 100644 --- a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCrafting.java +++ b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCrafting.java @@ -66,13 +66,8 @@ public void setContents(ItemStack result, ItemStack[] contents) { @Override public CraftItemStack getItem(int index) { - if (index < getResultInventory().getSize()) { - net.minecraft.server.ItemStack item = getResultInventory().getItem(index); - return item == null ? null : CraftItemStack.asCraftMirror(item); - } else { - net.minecraft.server.ItemStack item = getMatrixInventory().getItem(index - getResultInventory().getSize()); - return item == null ? null : CraftItemStack.asCraftMirror(item); - } + net.minecraft.server.ItemStack item = (index < getResultInventory().getSize() ? getResultInventory().getItem(index) : getMatrixInventory().getItem(index - getResultInventory().getSize())); + return item == null ? null : CraftItemStack.asCraftMirror(item); } @Override diff --git a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java index 0ee11471..289142c2 100644 --- a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java +++ b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java @@ -26,13 +26,13 @@ ScoreboardObjective getHandle() { } public String getName() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); return objective.getName(); } public String getDisplayName() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); return objective.getDisplayName(); } @@ -40,19 +40,19 @@ public String getDisplayName() throws IllegalStateException { public void setDisplayName(String displayName) throws IllegalStateException, IllegalArgumentException { Validate.notNull(displayName, "Display name cannot be null"); Validate.isTrue(displayName.length() <= 32, "Display name '" + displayName + "' is longer than the limit of 32 characters"); - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); objective.setDisplayName(displayName); } public String getCriteria() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); return criteria.bukkitName; } public boolean isModifiable() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); return !criteria.criteria.isReadOnly(); } @@ -88,7 +88,7 @@ public DisplaySlot getDisplaySlot() throws IllegalStateException { public Score getScore(OfflinePlayer player) throws IllegalArgumentException, IllegalStateException { Validate.notNull(player, "Player cannot be null"); - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); return new CraftScore(this, player.getName()); } @@ -96,7 +96,7 @@ public Score getScore(OfflinePlayer player) throws IllegalArgumentException, Ill public Score getScore(String entry) throws IllegalArgumentException, IllegalStateException { Validate.notNull(entry, "Entry cannot be null"); if (entry.length() > 16) throw new IllegalArgumentException("Entry cannot be longer than 16 characters!"); // Spigot - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); return new CraftScore(this, entry); } diff --git a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java index a1864a58..980429e2 100644 --- a/nPaper-Server/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java +++ b/nPaper-Server/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java @@ -21,13 +21,13 @@ final class CraftTeam extends CraftScoreboardComponent implements Team { } public String getName() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); return team.getName(); } public String getDisplayName() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); return team.getDisplayName(); } @@ -35,13 +35,13 @@ public String getDisplayName() throws IllegalStateException { public void setDisplayName(String displayName) throws IllegalStateException { Validate.notNull(displayName, "Display name cannot be null"); Validate.isTrue(displayName.length() <= 32, "Display name '" + displayName + "' is longer than the limit of 32 characters"); - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); team.setDisplayName(displayName); } public String getPrefix() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); return team.getPrefix(); } @@ -49,13 +49,13 @@ public String getPrefix() throws IllegalStateException { public void setPrefix(String prefix) throws IllegalStateException, IllegalArgumentException { Validate.notNull(prefix, "Prefix cannot be null"); Validate.isTrue(prefix.length() <= 32, "Prefix '" + prefix + "' is longer than the limit of 32 characters"); - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); team.setPrefix(prefix); } public String getSuffix() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); return team.getSuffix(); } @@ -63,37 +63,37 @@ public String getSuffix() throws IllegalStateException { public void setSuffix(String suffix) throws IllegalStateException, IllegalArgumentException { Validate.notNull(suffix, "Suffix cannot be null"); Validate.isTrue(suffix.length() <= 32, "Suffix '" + suffix + "' is longer than the limit of 32 characters"); - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); team.setSuffix(suffix); } public boolean allowFriendlyFire() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); return team.allowFriendlyFire(); } public void setAllowFriendlyFire(boolean enabled) throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); team.setAllowFriendlyFire(enabled); } public boolean canSeeFriendlyInvisibles() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); return team.canSeeFriendlyInvisibles(); } public void setCanSeeFriendlyInvisibles(boolean enabled) throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); team.setCanSeeFriendlyInvisibles(enabled); } public Set getPlayers() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); ImmutableSet.Builder players = ImmutableSet.builder(); for (Object o : team.getPlayerNameSet()) { @@ -105,7 +105,7 @@ public Set getPlayers() throws IllegalStateException { // Spigot start @Override public Set getEntries() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); ImmutableSet.Builder entries = ImmutableSet.builder(); for (Object o : team.getPlayerNameSet()){ @@ -116,7 +116,7 @@ public Set getEntries() throws IllegalStateException { // Spigot end public int getSize() throws IllegalStateException { - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); return team.getPlayerNameSet().size(); } @@ -163,7 +163,7 @@ public boolean hasPlayer(OfflinePlayer player) throws IllegalArgumentException, public boolean hasEntry(String entry) throws IllegalArgumentException, IllegalStateException { Validate.notNull("Entry cannot be null"); - CraftScoreboard scoreboard = checkState(); + //CraftScoreboard scoreboard = checkState(); return team.getPlayerNameSet().contains(entry); // Spigot end diff --git a/pom.xml b/pom.xml index f55efc10..70f7c8b8 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.sonatype.oss oss-parent - 7 + 9 com.sathonay.npaper @@ -24,9 +24,9 @@ nPaper-API - - UTF-8 - + + clean install + diff --git a/setup-minecraft-server.sh b/setup-minecraft-server.sh deleted file mode 100644 index 0eee6d4c..00000000 --- a/setup-minecraft-server.sh +++ /dev/null @@ -1,5 +0,0 @@ -cd $HOME/.m2/repository -curl https://download1480.mediafire.com/fjej4p9wqxzg/dtkp7ubl3zivph2/minecraft-server-repo.zip -O minecraft-server-repo.zip -unzip -o minecraft-server-repo.zip -rm minecraft-server-repo.zip -echo "script ended \_(^^)_/"