package openmods.network.event; import com.google.common.base.Preconditions; import com.google.common.base.Throwables; import com.google.common.collect.Maps; import gnu.trove.map.hash.TIntObjectHashMap; import java.util.Map; import openmods.datastore.IDataVisitor; public class NetworkEventRegistry implements IDataVisitor<String, Integer> { private final TIntObjectHashMap<INetworkEventType> idToType = new TIntObjectHashMap<INetworkEventType>(); private final Map<Class<? extends NetworkEvent>, Integer> clsToId = Maps.newIdentityHashMap(); public NetworkEventRegistry() {} int getIdForClass(Class<? extends NetworkEvent> cls) { Integer result = clsToId.get(cls); Preconditions.checkNotNull(result, "Class %s is not registered", cls); return result; } INetworkEventType getTypeForId(int id) { INetworkEventType result = idToType.get(id); Preconditions.checkNotNull(result, "Id %s is not registered", id); return result; } @Override public void begin(int size) { idToType.clear(); clsToId.clear(); } public static INetworkEventType createPacketType(final Class<? extends NetworkEvent> cls) { final NetworkEventMeta meta = cls.getAnnotation(NetworkEventMeta.class); final NetworkEventCustomType customType = cls.getAnnotation(NetworkEventCustomType.class); if (customType != null) { Preconditions.checkState(meta == null, "NetworkEventMeta and NetworkEventCustomType are mutually exclusive"); try { return customType.value().newInstance(); } catch (Exception e) { throw Throwables.propagate(e); } } final boolean isCompressed; final boolean isChunked; final EventDirection direction; if (meta != null) { isChunked = meta.chunked(); isCompressed = meta.compressed(); direction = meta.direction(); } else { isChunked = false; isCompressed = false; direction = EventDirection.ANY; } return new INetworkEventType() { @Override public boolean isCompressed() { return isCompressed; } @Override public boolean isChunked() { return isChunked; } @Override public EventDirection getDirection() { return direction; } @Override public NetworkEvent createPacket() { try { return cls.newInstance(); } catch (Exception e) { throw Throwables.propagate(e); } } }; } @Override public void entry(String clsKey, Integer eventId) { Class<?> candidateCls; try { candidateCls = Class.forName(clsKey); } catch (ClassNotFoundException e) { throw new IllegalArgumentException(String.format("Can't find class %s", clsKey), e); } Preconditions.checkArgument(NetworkEvent.class.isAssignableFrom(candidateCls)); @SuppressWarnings("unchecked") Class<? extends NetworkEvent> cls = (Class<? extends NetworkEvent>)candidateCls; INetworkEventType type = createPacketType(cls); idToType.put(eventId, type); clsToId.put(cls, eventId); } @Override public void end() {} }