2013-03-08 00:25:48 +00:00
/ *
* Forge Mod Loader
* Copyright ( c ) 2012 - 2013 cpw .
* All rights reserved . This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2 . 1
* which accompanies this distribution , and is available at
* http : //www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors :
* cpw - implementation
* /
2012-08-06 13:52:42 +00:00
package cpw.mods.fml.common.network ;
2012-08-12 01:51:58 +00:00
import java.util.Arrays ;
2012-08-06 20:12:50 +00:00
import java.util.List ;
2012-08-06 13:52:42 +00:00
import java.util.Map ;
import java.util.Set ;
import java.util.logging.Level ;
2012-12-09 04:21:03 +00:00
import net.minecraft.entity.player.EntityPlayer ;
import net.minecraft.entity.player.EntityPlayerMP ;
import net.minecraft.inventory.Container ;
import net.minecraft.network.* ;
import net.minecraft.network.packet.* ;
2012-08-08 04:31:24 +00:00
import net.minecraft.server.MinecraftServer ;
2012-12-09 04:21:03 +00:00
import net.minecraft.world.World ;
2012-08-06 13:52:42 +00:00
import com.google.common.base.Charsets ;
import com.google.common.base.Joiner ;
2012-08-06 20:12:50 +00:00
import com.google.common.base.Splitter ;
2012-08-08 00:10:36 +00:00
import com.google.common.base.Strings ;
2012-08-06 13:52:42 +00:00
import com.google.common.collect.ArrayListMultimap ;
2012-08-12 01:51:58 +00:00
import com.google.common.collect.Iterables ;
2012-08-06 20:12:50 +00:00
import com.google.common.collect.Lists ;
2012-08-06 13:52:42 +00:00
import com.google.common.collect.Maps ;
import com.google.common.collect.Multimap ;
2012-08-06 20:12:50 +00:00
import com.google.common.collect.Sets ;
2012-08-06 13:52:42 +00:00
2012-08-08 04:31:24 +00:00
import cpw.mods.fml.common.FMLCommonHandler ;
2012-08-06 13:52:42 +00:00
import cpw.mods.fml.common.FMLLog ;
2012-09-04 01:14:11 +00:00
import cpw.mods.fml.common.Loader ;
2012-08-06 13:52:42 +00:00
import cpw.mods.fml.common.ModContainer ;
2013-12-03 04:46:42 +00:00
import cpw.mods.fml.common.network.packet.FMLPacket ;
import cpw.mods.fml.common.network.packet.FMLPacket.Type ;
2012-12-16 04:21:26 +00:00
import cpw.mods.fml.relauncher.Side ;
2012-08-06 13:52:42 +00:00
2012-09-04 16:37:59 +00:00
/ * *
* @author cpw
*
* /
2012-08-06 13:52:42 +00:00
public class NetworkRegistry
{
private static final NetworkRegistry INSTANCE = new NetworkRegistry ( ) ;
/ * *
* A map of active channels per player
* /
private Multimap < Player , String > activeChannels = ArrayListMultimap . create ( ) ;
/ * *
2012-08-06 20:12:50 +00:00
* A map of the packet handlers for packets
2012-08-06 13:52:42 +00:00
* /
2012-08-13 02:23:03 +00:00
private Multimap < String , IPacketHandler > universalPacketHandlers = ArrayListMultimap . create ( ) ;
private Multimap < String , IPacketHandler > clientPacketHandlers = ArrayListMultimap . create ( ) ;
private Multimap < String , IPacketHandler > serverPacketHandlers = ArrayListMultimap . create ( ) ;
2012-08-06 20:12:50 +00:00
/ * *
* A linked set of registered connection handlers
* /
private Set < IConnectionHandler > connectionHandlers = Sets . newLinkedHashSet ( ) ;
2012-08-08 04:31:24 +00:00
private Map < ModContainer , IGuiHandler > serverGuiHandlers = Maps . newHashMap ( ) ;
private Map < ModContainer , IGuiHandler > clientGuiHandlers = Maps . newHashMap ( ) ;
2012-09-04 16:37:59 +00:00
private List < IChatListener > chatListeners = Lists . newArrayList ( ) ;
2012-08-06 13:52:42 +00:00
public static NetworkRegistry instance ( )
{
return INSTANCE ;
}
/ * *
* Get the packet 250 channel registration string
2013-01-22 02:37:29 +00:00
* @return the { @link Packet250CustomPayload } channel registration string
2012-08-06 13:52:42 +00:00
* /
2012-08-13 02:23:03 +00:00
byte [ ] getPacketRegistry ( Side side )
2012-08-06 13:52:42 +00:00
{
2012-08-13 02:23:03 +00:00
return Joiner . on ( '\0' ) . join ( Iterables . concat ( Arrays . asList ( " FML " ) , universalPacketHandlers . keySet ( ) , side . isClient ( ) ? clientPacketHandlers . keySet ( ) : serverPacketHandlers . keySet ( ) ) ) . getBytes ( Charsets . UTF_8 ) ;
2012-08-06 13:52:42 +00:00
}
/ * *
* Is the specified channel active for the player ?
* @param channel
* @param player
* /
public boolean isChannelActive ( String channel , Player player )
{
return activeChannels . containsEntry ( player , channel ) ;
}
/ * *
* register a channel to a mod
2013-01-22 02:37:29 +00:00
* @param handler the packet handler
* @param channelName the channel name to register it with
2012-08-06 13:52:42 +00:00
* /
2012-08-06 20:12:50 +00:00
public void registerChannel ( IPacketHandler handler , String channelName )
2012-08-06 13:52:42 +00:00
{
2012-08-17 20:59:48 +00:00
if ( Strings . isNullOrEmpty ( channelName ) | | ( channelName ! = null & & channelName . length ( ) > 16 ) )
{
FMLLog . severe ( " Invalid channel name '%s' : %s " , channelName , Strings . isNullOrEmpty ( channelName ) ? " Channel name is empty " : " Channel name is too long (16 chars is maximum) " ) ;
throw new RuntimeException ( " Channel name is invalid " ) ;
}
2012-08-13 02:23:03 +00:00
universalPacketHandlers . put ( channelName , handler ) ;
}
public void registerChannel ( IPacketHandler handler , String channelName , Side side )
{
2012-08-18 13:28:36 +00:00
if ( side = = null )
{
registerChannel ( handler , channelName ) ;
return ;
}
2012-08-17 20:59:48 +00:00
if ( Strings . isNullOrEmpty ( channelName ) | | ( channelName ! = null & & channelName . length ( ) > 16 ) )
{
FMLLog . severe ( " Invalid channel name '%s' : %s " , channelName , Strings . isNullOrEmpty ( channelName ) ? " Channel name is empty " : " Channel name is too long (16 chars is maximum) " ) ;
throw new RuntimeException ( " Channel name is invalid " ) ;
}
2012-08-13 02:23:03 +00:00
if ( side . isClient ( ) )
{
clientPacketHandlers . put ( channelName , handler ) ;
}
else
{
serverPacketHandlers . put ( channelName , handler ) ;
}
2012-08-06 13:52:42 +00:00
}
/ * *
* Activate the channel for the player
* @param player
* /
2012-08-06 20:12:50 +00:00
void activateChannel ( Player player , String channel )
2012-08-06 13:52:42 +00:00
{
activeChannels . put ( player , channel ) ;
}
/ * *
* Deactivate the channel for the player
* @param player
* @param channel
* /
2012-08-06 20:12:50 +00:00
void deactivateChannel ( Player player , String channel )
2012-08-06 13:52:42 +00:00
{
activeChannels . remove ( player , channel ) ;
}
2012-08-06 20:12:50 +00:00
/ * *
* Register a connection handler
*
* @param handler
* /
public void registerConnectionHandler ( IConnectionHandler handler )
{
connectionHandlers . add ( handler ) ;
}
2012-09-04 16:37:59 +00:00
/ * *
* Register a chat listener
* @param listener
* /
public void registerChatListener ( IChatListener listener )
{
chatListeners . add ( listener ) ;
}
2012-10-20 21:07:59 +00:00
void playerLoggedIn ( EntityPlayerMP player , NetServerHandler netHandler , INetworkManager manager )
2012-08-06 20:12:50 +00:00
{
2012-08-13 15:58:44 +00:00
generateChannelRegistration ( player , netHandler , manager ) ;
2012-08-06 20:12:50 +00:00
for ( IConnectionHandler handler : connectionHandlers )
{
handler . playerLoggedIn ( ( Player ) player , netHandler , manager ) ;
}
}
2012-10-20 21:07:59 +00:00
String connectionReceived ( NetLoginHandler netHandler , INetworkManager manager )
2012-08-08 00:10:36 +00:00
{
for ( IConnectionHandler handler : connectionHandlers )
{
String kick = handler . connectionReceived ( netHandler , manager ) ;
if ( ! Strings . isNullOrEmpty ( kick ) )
{
return kick ;
}
}
return null ;
}
2012-10-20 21:07:59 +00:00
void connectionOpened ( NetHandler netClientHandler , String server , int port , INetworkManager networkManager )
2012-08-08 00:41:37 +00:00
{
for ( IConnectionHandler handler : connectionHandlers )
{
handler . connectionOpened ( netClientHandler , server , port , networkManager ) ;
}
}
2012-10-20 21:07:59 +00:00
void connectionOpened ( NetHandler netClientHandler , MinecraftServer server , INetworkManager networkManager )
2012-08-08 00:41:37 +00:00
{
for ( IConnectionHandler handler : connectionHandlers )
{
handler . connectionOpened ( netClientHandler , server , networkManager ) ;
}
}
2012-10-20 21:07:59 +00:00
void clientLoggedIn ( NetHandler clientHandler , INetworkManager manager , Packet1Login login )
2012-08-08 00:41:37 +00:00
{
2012-08-13 15:58:44 +00:00
generateChannelRegistration ( clientHandler . getPlayer ( ) , clientHandler , manager ) ;
2012-08-08 00:41:37 +00:00
for ( IConnectionHandler handler : connectionHandlers )
{
2012-08-11 15:01:18 +00:00
handler . clientLoggedIn ( clientHandler , manager , login ) ;
2012-08-08 00:41:37 +00:00
}
}
2012-10-20 21:07:59 +00:00
void connectionClosed ( INetworkManager manager , EntityPlayer player )
2012-08-08 00:41:37 +00:00
{
for ( IConnectionHandler handler : connectionHandlers )
{
handler . connectionClosed ( manager ) ;
}
2012-09-15 19:36:26 +00:00
activeChannels . removeAll ( player ) ;
2012-08-08 00:41:37 +00:00
}
2012-08-10 15:12:57 +00:00
2012-10-20 21:07:59 +00:00
void generateChannelRegistration ( EntityPlayer player , NetHandler netHandler , INetworkManager manager )
2012-08-06 20:12:50 +00:00
{
Packet250CustomPayload pkt = new Packet250CustomPayload ( ) ;
pkt . field_73630_a = " REGISTER " ;
2012-08-13 02:23:03 +00:00
pkt . field_73629_c = getPacketRegistry ( player instanceof EntityPlayerMP ? Side . SERVER : Side . CLIENT ) ;
2012-08-06 20:12:50 +00:00
pkt . field_73628_b = pkt . field_73629_c . length ;
manager . func_74429_a ( pkt ) ;
}
2012-10-20 21:07:59 +00:00
void handleCustomPacket ( Packet250CustomPayload packet , INetworkManager network , NetHandler handler )
2012-08-06 20:12:50 +00:00
{
if ( " REGISTER " . equals ( packet . field_73630_a ) )
{
handleRegistrationPacket ( packet , ( Player ) handler . getPlayer ( ) ) ;
}
else if ( " UNREGISTER " . equals ( packet . field_73630_a ) )
{
handleUnregistrationPacket ( packet , ( Player ) handler . getPlayer ( ) ) ;
}
else
{
handlePacket ( packet , network , ( Player ) handler . getPlayer ( ) ) ;
}
}
2012-10-20 21:07:59 +00:00
private void handlePacket ( Packet250CustomPayload packet , INetworkManager network , Player player )
2012-08-06 20:12:50 +00:00
{
2012-08-15 23:54:56 +00:00
String channel = packet . field_73630_a ;
2012-08-27 21:46:08 +00:00
for ( IPacketHandler handler : Iterables . concat ( universalPacketHandlers . get ( channel ) , player instanceof EntityPlayerMP ? serverPacketHandlers . get ( channel ) : clientPacketHandlers . get ( channel ) ) )
2012-08-06 20:12:50 +00:00
{
2012-08-27 21:46:08 +00:00
handler . onPacketData ( network , packet , player ) ;
2012-08-06 20:12:50 +00:00
}
}
private void handleRegistrationPacket ( Packet250CustomPayload packet , Player player )
{
List < String > channels = extractChannelList ( packet ) ;
for ( String channel : channels )
{
activateChannel ( player , channel ) ;
}
}
private void handleUnregistrationPacket ( Packet250CustomPayload packet , Player player )
{
List < String > channels = extractChannelList ( packet ) ;
for ( String channel : channels )
{
deactivateChannel ( player , channel ) ;
}
}
2012-09-16 01:04:56 +00:00
2012-08-06 20:12:50 +00:00
private List < String > extractChannelList ( Packet250CustomPayload packet )
{
String request = new String ( packet . field_73629_c , Charsets . UTF_8 ) ;
List < String > channels = Lists . newArrayList ( Splitter . on ( '\0' ) . split ( request ) ) ;
return channels ;
}
2012-08-10 15:12:57 +00:00
public void registerGuiHandler ( Object mod , IGuiHandler handler )
{
ModContainer mc = FMLCommonHandler . instance ( ) . findContainerFor ( mod ) ;
2012-09-04 01:14:11 +00:00
if ( mc = = null )
{
mc = Loader . instance ( ) . activeModContainer ( ) ;
FMLLog . log ( Level . WARNING , " Mod %s attempted to register a gui network handler during a construction phase " , mc . getModId ( ) ) ;
}
2012-08-10 15:12:57 +00:00
NetworkModHandler nmh = FMLNetworkHandler . instance ( ) . findNetworkModHandler ( mc ) ;
if ( nmh = = null )
{
FMLLog . log ( Level . FINE , " The mod %s needs to be a @NetworkMod to register a Networked Gui Handler " , mc . getModId ( ) ) ;
}
else
{
serverGuiHandlers . put ( mc , handler ) ;
}
clientGuiHandlers . put ( mc , handler ) ;
}
void openRemoteGui ( ModContainer mc , EntityPlayerMP player , int modGuiId , World world , int x , int y , int z )
2012-08-08 04:31:24 +00:00
{
2012-08-10 15:12:57 +00:00
IGuiHandler handler = serverGuiHandlers . get ( mc ) ;
NetworkModHandler nmh = FMLNetworkHandler . instance ( ) . findNetworkModHandler ( mc ) ;
if ( handler ! = null & & nmh ! = null )
2012-08-08 04:31:24 +00:00
{
Container container = ( Container ) handler . getServerGuiElement ( modGuiId , player , world , x , y , z ) ;
if ( container ! = null )
{
player . func_71117_bO ( ) ;
player . func_71128_l ( ) ;
int windowId = player . field_71139_cq ;
Packet250CustomPayload pkt = new Packet250CustomPayload ( ) ;
pkt . field_73630_a = " FML " ;
2012-08-10 15:12:57 +00:00
pkt . field_73629_c = FMLPacket . makePacket ( Type . GUIOPEN , windowId , nmh . getNetworkId ( ) , modGuiId , x , y , z ) ;
2012-08-08 04:31:24 +00:00
pkt . field_73628_b = pkt . field_73629_c . length ;
player . field_71135_a . func_72567_b ( pkt ) ;
2012-08-10 15:12:57 +00:00
player . field_71070_bA = container ;
2012-08-08 04:31:24 +00:00
player . field_71070_bA . field_75152_c = windowId ;
player . field_71070_bA . func_75132_a ( player ) ;
}
}
}
2012-08-10 15:12:57 +00:00
void openLocalGui ( ModContainer mc , EntityPlayer player , int modGuiId , World world , int x , int y , int z )
2012-08-08 04:31:24 +00:00
{
2012-08-10 15:12:57 +00:00
IGuiHandler handler = clientGuiHandlers . get ( mc ) ;
2012-08-08 04:31:24 +00:00
FMLCommonHandler . instance ( ) . showGuiScreen ( handler . getClientGuiElement ( modGuiId , player , world , x , y , z ) ) ;
}
2012-09-04 16:37:59 +00:00
public Packet3Chat handleChat ( NetHandler handler , Packet3Chat chat )
{
Side s = Side . CLIENT ;
if ( handler instanceof NetServerHandler )
{
s = Side . SERVER ;
}
for ( IChatListener listener : chatListeners )
{
chat = s . isClient ( ) ? listener . clientChat ( handler , chat ) : listener . serverChat ( handler , chat ) ;
}
return chat ;
}
2012-09-06 14:03:30 +00:00
public void handleTinyPacket ( NetHandler handler , Packet131MapData mapData )
{
2012-09-07 10:35:26 +00:00
NetworkModHandler nmh = FMLNetworkHandler . instance ( ) . findNetworkModHandler ( ( int ) mapData . field_73438_a ) ;
2012-09-06 14:03:30 +00:00
if ( nmh = = null )
{
FMLLog . info ( " Received a tiny packet for network id %d that is not recognised here " , mapData . field_73438_a ) ;
return ;
}
if ( nmh . hasTinyPacketHandler ( ) )
{
nmh . getTinyPacketHandler ( ) . handle ( handler , mapData ) ;
}
else
{
FMLLog . info ( " Received a tiny packet for a network mod that does not accept tiny packets %s " , nmh . getContainer ( ) . getModId ( ) ) ;
}
}
2012-08-06 13:52:42 +00:00
}