summaryrefslogtreecommitdiffstats
path: root/src/main/java/net/minecraft/server/MinecraftServer.java
diff options
context:
space:
mode:
authorWesley Wolfe <weswolf@aol.com>2012-10-07 15:08:21 -0500
committerWesley Wolfe <weswolf@aol.com>2012-10-14 17:26:53 -0500
commit05e889f3468b07b2897d64ee1df3e26e763408b1 (patch)
treedb61d53a6e329fbd5185bf2f2475fdf7aab3d5b0 /src/main/java/net/minecraft/server/MinecraftServer.java
parent93a79cd0e646318ee23db6842cbba0acb107c389 (diff)
downloadcraftbukkit-05e889f3468b07b2897d64ee1df3e26e763408b1.tar
craftbukkit-05e889f3468b07b2897d64ee1df3e26e763408b1.tar.gz
craftbukkit-05e889f3468b07b2897d64ee1df3e26e763408b1.tar.lz
craftbukkit-05e889f3468b07b2897d64ee1df3e26e763408b1.tar.xz
craftbukkit-05e889f3468b07b2897d64ee1df3e26e763408b1.zip
Queue tasks from secondary threads. Fixes BUKKIT-2546 and BUKKIT-2600
This change affects the old chat compatibility layer from an implementation only standpoint. It does not queue the 'event' to fire, but rather queues a runnable that allows the calling thread to wait for execution to finish. The other effect of this change is that rcon connects now have their commands queued to be run on next server tick using the same implementation. The internal implementation is in org.bukkit.craftbukkit.util.Waitable. It is very similar to a Future<T> task, but only contains minimal implementation with object.wait() and object.notify() calls under the hood of waitable.get() and waitable.run(). PlayerPreLoginEvent now properly implements thread-safe event execution by queuing the events similar to chat and rcon. This is still a poor way albeit proper way to implement thread-safety; PlayerPreLoginEvent will stay deprecated.
Diffstat (limited to 'src/main/java/net/minecraft/server/MinecraftServer.java')
-rw-r--r--src/main/java/net/minecraft/server/MinecraftServer.java61
1 files changed, 30 insertions, 31 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() {