buildcraft/common/buildcraft/core/network/NetworkIdRegistry.java

161 lines
4.3 KiB
Java
Raw Normal View History

package buildcraft.core.network;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Map;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.NetHandlerPlayServer;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent.ServerTickEvent;
import cpw.mods.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent;
import cpw.mods.fml.common.network.FMLNetworkEvent.ServerConnectionFromClientEvent;
import buildcraft.core.utils.Utils;
public class NetworkIdRegistry {
public static NetworkIdRegistry instance;
private static boolean isLocal = false;
private static boolean isMaster = false;
private static BiMap<String, Integer> idMap = HashBiMap.create();
private static LinkedList<EntityPlayerMP> playersToInitialize = new LinkedList<EntityPlayerMP>();
public NetworkIdRegistry() {
FMLCommonHandler.instance().bus().register(this);
}
public static void write(ByteBuf buf, String strId) {
if (!isMaster) {
if (!idMap.containsKey(strId)) {
buf.writeInt(-1);
Utils.writeUTF(buf, strId);
} else {
buf.writeInt(idMap.get(strId));
}
} else {
if (!idMap.containsKey(strId)) {
idMap.put(strId, idMap.size());
if (!isLocal) {
RPCHandler.rpcBroadcastAllPlayers(NetworkIdRegistry.class, "receiveId", strId, idMap.size() - 1);
}
}
buf.writeInt(idMap.get(strId));
}
}
public static String read(ByteBuf buf) {
int id = buf.readInt();
if (!isMaster) {
if (!idMap.inverse().containsKey(id)) {
RPCHandler.rpcServer(NetworkIdRegistry.class, "requestId", id);
throw new IllegalArgumentException("Id " + id + " unknown by the registry.");
} else {
return idMap.inverse().get(id);
}
} else {
if (id == -1) {
String str = Utils.readUTF(buf);
if (!idMap.containsKey(str)) {
idMap.put(str, idMap.size());
}
return str;
} else {
return idMap.inverse().get(id);
}
}
}
@RPC(RPCSide.SERVER)
private static void requestId(int id, RPCMessageInfo info) {
if (!idMap.inverse().containsKey(id)) {
throw new IllegalArgumentException("Id " + id + " unknown by the registry.");
} else {
RPCHandler.rpcPlayer(info.sender, NetworkIdRegistry.class, "receiveId", idMap.inverse().get(id), id);
}
}
@RPC(RPCSide.SERVER)
private static void receiveId(String str, int id) {
idMap.put(str, id);
}
private static void sendAllIdsTo(EntityPlayerMP player) {
ArrayList<String> idStr = new ArrayList<String>();
ArrayList<Integer> ids = new ArrayList<Integer>();
for (Map.Entry<String, Integer> e : idMap.entrySet()) {
idStr.add(e.getKey());
ids.add(e.getValue());
}
RPCHandler.rpcPlayer(player, NetworkIdRegistry.class, "receiveAllIds", idStr, ids);
}
@RPC(RPCSide.CLIENT)
private static void receiveAllIds(ArrayList<String> idStr, ArrayList<Integer> ids) {
idMap.clear();
for (int i = 0; i < idStr.size(); ++i) {
if (!idMap.containsKey(idStr.get(i))) {
System.out.println("INIT " + ids.get(i) + " => " + idStr.get(i));
idMap.put(idStr.get(i), ids.get(i));
}
}
}
@SubscribeEvent
public void serverConnected(ServerConnectionFromClientEvent evt) {
isMaster = true;
if (evt.isLocal) {
isLocal = true;
} else {
isLocal = false;
// the server cannot send messages to the client at this stage, so
// cache the new client to receive ids on the next tick.
playersToInitialize.add(((NetHandlerPlayServer) evt.handler).playerEntity);
}
}
@SubscribeEvent
public void serverConnected(ClientConnectedToServerEvent evt) {
if (!evt.isLocal) {
isMaster = false;
isLocal = false;
}
}
@SubscribeEvent
public void tick(ServerTickEvent evt) {
for (EntityPlayerMP player : playersToInitialize) {
sendAllIdsTo(player);
}
playersToInitialize.clear();
}
static {
// The ids below are the minimal ids necessary to initialize properly
// the server. They are aimed at supporting the provide of receiveAllIds
idMap.put("", 0);
idMap.put(NetworkIdRegistry.class.getCanonicalName(), 1);
idMap.put(String.class.getCanonicalName(), 2);
idMap.put(Integer.class.getCanonicalName(), 3);
}
}