summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main/java/net/minecraft/server/MinecraftServer.java61
-rw-r--r--src/main/java/net/minecraft/server/NetServerHandler.java41
-rw-r--r--src/main/java/net/minecraft/server/ThreadLoginVerifier.java30
-rw-r--r--src/main/java/org/bukkit/craftbukkit/util/Waitable.java46
4 files changed, 136 insertions, 42 deletions
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 477de015..3fb1215c 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -13,13 +13,14 @@ import java.util.logging.Level;
import java.util.logging.Logger;
// CraftBukkit start
+import java.util.concurrent.ExecutionException;
import jline.console.ConsoleReader;
import joptsimple.OptionSet;
import org.bukkit.World.Environment;
+import org.bukkit.craftbukkit.util.Waitable;
import org.bukkit.event.server.RemoteServerCommandEvent;
import org.bukkit.event.world.WorldSaveEvent;
-import org.bukkit.event.player.PlayerChatEvent;
// CraftBukkit end
public abstract class MinecraftServer implements Runnable, IMojangStatistics, ICommandListener {
@@ -79,7 +80,7 @@ public abstract class MinecraftServer implements Runnable, IMojangStatistics, IC
public ConsoleReader reader;
public static int currentTick;
public final Thread primaryThread;
- public java.util.Queue<PlayerChatEvent> chatQueue = new java.util.concurrent.ConcurrentLinkedQueue<PlayerChatEvent>();
+ public java.util.Queue<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>();
public int autosavePeriod;
// CraftBukkit end
@@ -508,26 +509,9 @@ public abstract class MinecraftServer implements Runnable, IMojangStatistics, IC
// CraftBukkit start - only send timeupdates to the people in that world
this.server.getScheduler().mainThreadHeartbeat(this.ticks);
- // Fix for old plugins still using deprecated event
- while (!chatQueue.isEmpty()) {
- PlayerChatEvent event = chatQueue.remove();
- org.bukkit.Bukkit.getPluginManager().callEvent(event);
-
- if (event.isCancelled()) {
- continue;
- }
-
- String message = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage());
- console.sendMessage(message);
- if (((org.bukkit.craftbukkit.util.LazyPlayerSet) event.getRecipients()).isLazy()) {
- for (Object player : getServerConfigurationManager().players) {
- ((EntityPlayer) player).sendMessage(message);
- }
- } else {
- for (org.bukkit.entity.Player player : event.getRecipients()) {
- player.sendMessage(message);
- }
- }
+ // Run tasks that are waiting on processing
+ while (!processQueue.isEmpty()) {
+ processQueue.remove().run();
}
// Send timeupdates to everyone, it will get the right time from the world the player is in.
@@ -782,16 +766,31 @@ public abstract class MinecraftServer implements Runnable, IMojangStatistics, IC
// CraftBukkit end
}
- public String i(String s) {
- RemoteControlCommandListener.instance.b();
- // CraftBukkit start
- RemoteServerCommandEvent event = new RemoteServerCommandEvent(this.remoteConsole, s);
- this.server.getPluginManager().callEvent(event);
- ServerCommand servercommand = new ServerCommand(event.getCommand(), RemoteControlCommandListener.instance);
- // this.q.a(RemoteControlCommandListener.instance, s);
- this.server.dispatchServerCommand(this.remoteConsole, servercommand); // CraftBukkit
+ // CraftBukkit start
+ public String i(final String s) { // CraftBukkit - final parameter
+ Waitable<String> waitable = new Waitable<String>() {
+ @Override
+ protected String evaluate() {
+ RemoteControlCommandListener.instance.b();
+ // Event changes start
+ RemoteServerCommandEvent event = new RemoteServerCommandEvent(MinecraftServer.this.remoteConsole, s);
+ MinecraftServer.this.server.getPluginManager().callEvent(event);
+ // Event changes end
+ ServerCommand servercommand = new ServerCommand(event.getCommand(), RemoteControlCommandListener.instance);
+ // this.q.a(RemoteControlCommandListener.instance, s);
+ MinecraftServer.this.server.dispatchServerCommand(MinecraftServer.this.remoteConsole, servercommand); // CraftBukkit
+ return RemoteControlCommandListener.instance.c();
+ }};
+ processQueue.add(waitable);
+ try {
+ return waitable.get();
+ } catch (ExecutionException e) {
+ throw new RuntimeException("Exception processing rcon command " + s, e.getCause());
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt(); // Maintain interrupted state
+ throw new RuntimeException("Interrupted processing rcon command " + s, e);
+ }
// CraftBukkit end
- return RemoteControlCommandListener.instance.c();
}
public boolean isDebugging() {
diff --git a/src/main/java/net/minecraft/server/NetServerHandler.java b/src/main/java/net/minecraft/server/NetServerHandler.java
index b27cc152..d41da15f 100644
--- a/src/main/java/net/minecraft/server/NetServerHandler.java
+++ b/src/main/java/net/minecraft/server/NetServerHandler.java
@@ -13,11 +13,13 @@ import java.io.UnsupportedEncodingException;
import java.util.logging.Level;
import java.util.HashSet;
+import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.inventory.CraftInventoryView;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.util.LazyPlayerSet;
+import org.bukkit.craftbukkit.util.Waitable;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.craftbukkit.event.CraftEventFactory;
import org.bukkit.entity.Player;
@@ -832,9 +834,42 @@ public class NetServerHandler extends NetHandler {
if (PlayerChatEvent.getHandlerList().getRegisteredListeners().length != 0) {
// Evil plugins still listening to deprecated event
- PlayerChatEvent queueEvent = new PlayerChatEvent(player, event.getMessage(), event.getFormat(), event.getRecipients());
+ final PlayerChatEvent queueEvent = new PlayerChatEvent(player, event.getMessage(), event.getFormat(), event.getRecipients());
queueEvent.setCancelled(event.isCancelled());
- minecraftServer.chatQueue.add(queueEvent);
+ Waitable waitable = new Waitable() {
+ @Override
+ protected Object evaluate() {
+ Bukkit.getPluginManager().callEvent(queueEvent);
+
+ if (queueEvent.isCancelled()) {
+ return null;
+ }
+
+ String message = String.format(queueEvent.getFormat(), queueEvent.getPlayer().getDisplayName(), queueEvent.getMessage());
+ NetServerHandler.this.minecraftServer.console.sendMessage(message);
+ if (((LazyPlayerSet) queueEvent.getRecipients()).isLazy()) {
+ for (Object player : NetServerHandler.this.minecraftServer.getServerConfigurationManager().players) {
+ ((EntityPlayer) player).sendMessage(message);
+ }
+ } else {
+ for (Player player : queueEvent.getRecipients()) {
+ player.sendMessage(message);
+ }
+ }
+ return null;
+ }};
+ if (async) {
+ minecraftServer.processQueue.add(waitable);
+ } else {
+ waitable.run();
+ }
+ try {
+ waitable.get();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on!
+ } catch (java.util.concurrent.ExecutionException e) {
+ throw new RuntimeException("Exception processing chat event", e.getCause());
+ }
} else {
if (event.isCancelled()) {
return;
@@ -1047,7 +1082,7 @@ public class NetServerHandler extends NetHandler {
PlayerPortalEvent event = new PlayerPortalEvent(this.player.getBukkitEntity(), this.player.getBukkitEntity().getLocation(), toLocation, pta, PlayerPortalEvent.TeleportCause.END_PORTAL);
event.useTravelAgent(false);
- org.bukkit.Bukkit.getServer().getPluginManager().callEvent(event);
+ Bukkit.getServer().getPluginManager().callEvent(event);
this.player = this.minecraftServer.getServerConfigurationManager().moveToWorld(this.player, 0, true, event.getTo());
// CraftBukkit end
} else if (this.player.q().getWorldData().isHardcore()) {
diff --git a/src/main/java/net/minecraft/server/ThreadLoginVerifier.java b/src/main/java/net/minecraft/server/ThreadLoginVerifier.java
index dba7d42a..08a2703d 100644
--- a/src/main/java/net/minecraft/server/ThreadLoginVerifier.java
+++ b/src/main/java/net/minecraft/server/ThreadLoginVerifier.java
@@ -8,6 +8,7 @@ import java.net.URLEncoder;
// CraftBukkit start
import org.bukkit.craftbukkit.CraftServer;
+import org.bukkit.craftbukkit.util.Waitable;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerPreLoginEvent;
// CraftBukkit end
@@ -46,15 +47,28 @@ class ThreadLoginVerifier extends Thread {
AsyncPlayerPreLoginEvent asyncEvent = new AsyncPlayerPreLoginEvent(NetLoginHandler.d(this.netLoginHandler), this.netLoginHandler.getSocket().getInetAddress());
this.server.getPluginManager().callEvent(asyncEvent);
- PlayerPreLoginEvent event = new PlayerPreLoginEvent(NetLoginHandler.d(this.netLoginHandler), this.netLoginHandler.getSocket().getInetAddress());
- if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) {
- event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage());
- }
- this.server.getPluginManager().callEvent(event);
+ if (PlayerPreLoginEvent.getHandlerList().getRegisteredListeners().length != 0) {
+ final PlayerPreLoginEvent event = new PlayerPreLoginEvent(NetLoginHandler.d(this.netLoginHandler), this.netLoginHandler.getSocket().getInetAddress());
+ if (asyncEvent.getResult() != PlayerPreLoginEvent.Result.ALLOWED) {
+ event.disallow(asyncEvent.getResult(), asyncEvent.getKickMessage());
+ }
+ Waitable<PlayerPreLoginEvent.Result> waitable = new Waitable<PlayerPreLoginEvent.Result>() {
+ @Override
+ protected PlayerPreLoginEvent.Result evaluate() {
+ ThreadLoginVerifier.this.server.getPluginManager().callEvent(event);
+ return event.getResult();
+ }};
- if (event.getResult() != PlayerPreLoginEvent.Result.ALLOWED) {
- this.netLoginHandler.disconnect(event.getKickMessage());
- return;
+ NetLoginHandler.b(this.netLoginHandler).processQueue.add(waitable);
+ if (waitable.get() != PlayerPreLoginEvent.Result.ALLOWED) {
+ this.netLoginHandler.disconnect(event.getKickMessage());
+ return;
+ }
+ } else {
+ if (asyncEvent.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
+ this.netLoginHandler.disconnect(asyncEvent.getKickMessage());
+ return;
+ }
}
// CraftBukkit end
diff --git a/src/main/java/org/bukkit/craftbukkit/util/Waitable.java b/src/main/java/org/bukkit/craftbukkit/util/Waitable.java
new file mode 100644
index 00000000..5cd11543
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/util/Waitable.java
@@ -0,0 +1,46 @@
+package org.bukkit.craftbukkit.util;
+
+import java.util.concurrent.ExecutionException;
+
+
+public abstract class Waitable<T> implements Runnable {
+ private enum Status {
+ WAITING,
+ RUNNING,
+ FINISHED,
+ }
+ Throwable t = null;
+ T value = null;
+ Status status = Status.WAITING;
+
+ public final void run() {
+ synchronized (this) {
+ if (status != Status.WAITING) {
+ throw new IllegalStateException("Invalid state " + status);
+ }
+ status = Status.RUNNING;
+ }
+ try {
+ value = evaluate();
+ } catch (Throwable t) {
+ this.t = t;
+ } finally {
+ synchronized (this) {
+ status = Status.FINISHED;
+ this.notifyAll();
+ }
+ }
+ }
+
+ protected abstract T evaluate();
+
+ public synchronized T get() throws InterruptedException, ExecutionException {
+ while (status != Status.FINISHED) {
+ this.wait();
+ }
+ if (t != null) {
+ throw new ExecutionException(t);
+ }
+ return value;
+ }
+}