Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package me.rabrg.mercury;
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.lang.reflect.Field;
- import java.lang.reflect.Modifier;
- import me.rabrg.mercury.event.Event;
- import me.rabrg.mercury.event.handler.EventHandler;
- /**
- * The core class of the Mercury networking API.
- * @author Ryan Greene
- *
- */
- public final class Mercury {
- /**
- * The modifiers field for allowing modification of final fields.
- */
- private static Field modifiersField;
- static {
- try {
- modifiersField = Field.class.getDeclaredField("modifiers");
- } catch (final Exception e) {
- System.out.println("Exception thrown while getting modifiers field " + e);
- System.exit(0);
- }
- modifiersField.setAccessible(true);
- }
- /**
- * An array containing all registered events.
- */
- private Class<Event>[] events;
- /**
- * An array containing all registered event handlers.
- */
- private EventHandler<Event>[] eventHandlers;
- /**
- * The current index for registering events.
- */
- private int index;
- /**
- * The input stream used to read events.
- */
- private final DataInputStream input;
- /**
- * The output stream used to write events.
- */
- private final DataOutputStream output;
- /**
- * Constructs a new mercury instance with the specified input and output streams.
- * @param input The input stream used to read events.
- * @param output The output stream used to write events.
- */
- @SuppressWarnings("unchecked")
- public Mercury(final InputStream input, final OutputStream output) {
- events = new Class[1];
- eventHandlers = new EventHandler[1];
- index = 0;
- this.input = new DataInputStream(input);
- this.output = new DataOutputStream(output);
- }
- /**
- * Registers the specified event to an opcode and the specified event handler.
- * @param event The event being registered.
- * @param eventHandler The handler of the event.
- */
- @SuppressWarnings("unchecked")
- public void registerEvent(final Class<? extends Event> event, final EventHandler<? extends Event> eventHandler) {
- if (index == events.length) {
- Class<Event>[] eventsExpanded = new Class[events.length + 1];
- System.arraycopy(events, 0, eventsExpanded, 0, events.length);
- events = eventsExpanded;
- EventHandler<Event>[] eventHandlersExpanded = new EventHandler[eventHandlers.length + 1];
- System.arraycopy(eventHandlers, 0, eventHandlersExpanded, 0, eventHandlers.length);
- eventHandlers = eventHandlersExpanded;
- }
- events[index] = (Class<Event>) event;
- eventHandlers[index++] = (EventHandler<Event>) eventHandler;
- }
- /**
- * Writes the specified event to the output stream.
- * @param event The event being written.
- * @throws Exception If an exception is thrown.
- */
- public void writeEvent(final Event event) throws Exception {
- int opcode = -1;
- for (int i = 0; i < events.length; i++) {
- if (events[i] == event.getClass()) {
- opcode = i;
- break;
- }
- }
- if (opcode == -1) {
- throw new IllegalArgumentException("The specified event is not registered " + event);
- }
- output.writeByte(opcode);
- for (final Field field : event.getClass().getDeclaredFields()) {
- field.setAccessible(true);
- modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
- final Class<?> type = field.getType();
- if (type == byte.class) {
- output.write(field.getByte(event));
- } else if (type == short.class) {
- output.writeShort(field.getShort(event));
- } else if (type == int.class) {
- output.writeInt(field.getInt(event));
- } else if (type == long.class) {
- output.writeLong(field.getLong(event));
- } else if (type == float.class) {
- output.writeFloat(field.getFloat(event));
- } else if (type == double.class) {
- output.writeDouble(field.getDouble(event));
- } else if (type == boolean.class) {
- output.writeBoolean(field.getBoolean(event));
- } else if (type == char.class) {
- output.writeChar(field.getChar(event));
- } else if (type == String.class) {
- output.writeUTF((String) field.get(event));
- } else {
- throw new IllegalStateException("The type " + type + " is not handled");
- }
- }
- output.flush();
- }
- /**
- * Reads an event from the input stream and passes it to its event handler.
- * @throws Exception If an exception is thrown.
- */
- public void readEvent() throws Exception {
- final int opcode = input.readByte();
- Event event = null;
- EventHandler<Event> eventHandler = null;
- try {
- event = (Event) events[opcode].newInstance();
- eventHandler = eventHandlers[opcode];
- } catch (final Exception e) {
- throw new IllegalStateException("Read opcode " + opcode + " but no event registered to it", e);
- }
- for (final Field field : event.getClass().getDeclaredFields()) {
- field.setAccessible(true);
- modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
- final Class<?> type = field.getType();
- if (type == byte.class) {
- field.setByte(event, input.readByte());
- } else if (type == short.class) {
- field.setShort(event, input.readShort());
- } else if (type == int.class) {
- field.setInt(event, input.readInt());
- } else if (type == long.class) {
- field.setLong(event, input.readLong());
- } else if (type == float.class) {
- field.setFloat(event, input.readFloat());
- } else if (type == double.class) {
- field.setDouble(event, input.readDouble());
- } else if (type == boolean.class) {
- field.setBoolean(event, input.readBoolean());
- } else if (type == char.class) {
- field.setChar(event, input.readChar());
- } else if (type == String.class) {
- field.set(event, input.readUTF());
- } else {
- throw new IllegalStateException("The type " + type + " is not handled");
- }
- }
- eventHandler.handleEvent(event);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement