Ensure that EntitySpawn and OpenGUI packets are handled in the world thread.

Also log all errors that are thrown in FutureTasks.
This commit is contained in:
Lex Manos 2014-12-13 17:45:38 -08:00
parent 5b07c7fead
commit e9dbc71362
9 changed files with 130 additions and 3 deletions

View File

@ -59,6 +59,15 @@
}
public boolean func_152349_b()
@@ -1000,7 +1004,7 @@
{
while (!this.field_152351_aB.isEmpty())
{
- ((FutureTask)this.field_152351_aB.poll()).run();
+ net.minecraftforge.fml.common.FMLCommonHandler.callFuture(((FutureTask)this.field_152351_aB.poll()));
}
}
@@ -1035,9 +1039,11 @@
if (!this.field_71454_w)

View File

@ -71,6 +71,15 @@
}
public void func_71190_q()
@@ -657,7 +671,7 @@
{
try
{
- ((FutureTask)this.field_175589_i.poll()).run();
+ net.minecraftforge.fml.common.FMLCommonHandler.callFuture(((FutureTask)this.field_175589_i.poll()));
}
catch (Throwable throwable2)
{
@@ -686,6 +700,7 @@
}

View File

@ -12,3 +12,12 @@
}
public void func_71217_p()
@@ -171,7 +172,7 @@
{
try
{
- ((FutureTask)this.field_175589_i.poll()).run();
+ net.minecraftforge.fml.common.FMLCommonHandler.callFuture(((FutureTask)this.field_175589_i.poll()));
}
catch (Throwable throwable)
{

View File

@ -53,7 +53,15 @@ import net.minecraft.network.INetHandler;
import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.ServerStatusResponse;
import net.minecraft.network.handshake.INetHandlerHandshakeServer;
import net.minecraft.network.login.INetHandlerLoginClient;
import net.minecraft.network.login.INetHandlerLoginServer;
import net.minecraft.network.play.INetHandlerPlayClient;
import net.minecraft.network.play.INetHandlerPlayServer;
import net.minecraft.network.status.INetHandlerStatusClient;
import net.minecraft.network.status.INetHandlerStatusServer;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.IThreadListener;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.WorldSettings;
import net.minecraft.world.storage.SaveFormatOld;
@ -842,4 +850,17 @@ public class FMLClientHandler implements IFMLSidedHandler
public void allowLogins() {
// NOOP for integrated server
}
@Override
public IThreadListener getWorldThread(INetHandler net)
{
if (net instanceof INetHandlerPlayClient ||
net instanceof INetHandlerLoginClient ||
net instanceof INetHandlerStatusClient) return getClient();
if (net instanceof INetHandlerHandshakeServer ||
net instanceof INetHandlerLoginServer ||
net instanceof INetHandlerPlayServer ||
net instanceof INetHandlerStatusServer) return getServer();
throw new RuntimeException("Unknown INetHandler: " + net);
}
}

View File

@ -18,6 +18,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import net.minecraft.crash.CrashReport;
@ -35,6 +37,7 @@ import net.minecraft.network.handshake.client.C00Handshake;
import net.minecraft.network.login.server.S00PacketDisconnect;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.IThreadListener;
import net.minecraft.world.World;
import net.minecraft.world.storage.SaveHandler;
import net.minecraft.world.storage.WorldInfo;
@ -660,4 +663,26 @@ public class FMLCommonHandler
Runtime.getRuntime().exit(exitCode);
}
}
public IThreadListener getWorldThread(INetHandler net)
{
return sidedDelegate.getWorldThread(net);
}
public static void callFuture(FutureTask task)
{
try
{
task.run();
task.get(); // Forces the exception to be thrown if any
}
catch (InterruptedException e)
{
FMLLog.log(Level.FATAL, e, "Exception caught executing FutureTask: " + e.toString());
}
catch (ExecutionException e)
{
FMLLog.log(Level.FATAL, e, "Exception caught executing FutureTask: " + e.toString());
}
}
}

View File

@ -19,6 +19,7 @@ import java.util.Set;
import net.minecraft.network.INetHandler;
import net.minecraft.network.NetworkManager;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.IThreadListener;
import net.minecraftforge.fml.common.eventhandler.EventBus;
import net.minecraftforge.fml.relauncher.Side;
@ -59,4 +60,6 @@ public interface IFMLSidedHandler
boolean shouldAllowPlayerLogins();
void allowLogins();
IThreadListener getWorldThread(INetHandler net);
}

View File

@ -11,11 +11,14 @@ import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.util.IThreadListener;
import net.minecraft.world.World;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.internal.FMLMessage.EntityAdjustMessage;
import net.minecraftforge.fml.common.network.internal.FMLMessage.EntityMessage;
import net.minecraftforge.fml.common.registry.EntityRegistry;
@ -27,7 +30,26 @@ import com.google.common.base.Throwables;
public class EntitySpawnHandler extends SimpleChannelInboundHandler<FMLMessage.EntityMessage> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, EntityMessage msg) throws Exception
protected void channelRead0(ChannelHandlerContext ctx, final EntityMessage msg) throws Exception
{
IThreadListener thread = FMLCommonHandler.instance().getWorldThread(ctx.channel().attr(NetworkRegistry.NET_HANDLER).get());
if (thread.isCallingFromMinecraftThread())
{
process(msg);
}
else
{
thread.addScheduledTask(new Runnable()
{
public void run()
{
EntitySpawnHandler.this.process(msg);
}
});
}
}
private void process(EntityMessage msg)
{
if (msg.getClass().equals(FMLMessage.EntitySpawnMessage.class))
{
@ -52,7 +74,6 @@ public class EntitySpawnHandler extends SimpleChannelInboundHandler<FMLMessage.E
{
FMLLog.fine("Attempted to adjust the position of entity %d which is not present on the client", msg.entityId);
}
}
private void spawnEntity(FMLMessage.EntitySpawnMessage spawnMsg)

View File

@ -3,15 +3,37 @@ package net.minecraftforge.fml.common.network.internal;
import org.apache.logging.log4j.Level;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.IThreadListener;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.internal.FMLMessage.OpenGui;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
public class OpenGuiHandler extends SimpleChannelInboundHandler<FMLMessage.OpenGui> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, OpenGui msg) throws Exception
protected void channelRead0(ChannelHandlerContext ctx, final OpenGui msg) throws Exception
{
IThreadListener thread = FMLCommonHandler.instance().getWorldThread(ctx.channel().attr(NetworkRegistry.NET_HANDLER).get());
if (thread.isCallingFromMinecraftThread())
{
process(msg);
}
else
{
thread.addScheduledTask(new Runnable()
{
public void run()
{
OpenGuiHandler.this.process(msg);
}
});
}
}
private void process(OpenGui msg)
{
EntityPlayer player = FMLClientHandler.instance().getClient().thePlayer;
player.openGui(msg.modId, msg.modGuiId, player.worldObj, msg.x, msg.y, msg.z);

View File

@ -23,6 +23,7 @@ import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.NetworkManager;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.util.IThreadListener;
import net.minecraft.world.storage.SaveFormatOld;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
@ -258,4 +259,11 @@ public class FMLServerHandler implements IFMLSidedHandler
public void allowLogins() {
DedicatedServer.allowPlayerLogins = true;
}
@Override
public IThreadListener getWorldThread(INetHandler net)
{
// Always the server on the dedicated server, eventually add Per-World if Mojang adds world stuff.
return getServer();
}
}