gt: 		if (closed) return;
context: package gminers.glasspane.ease;
  
  
  import java.awt.Color;
  import java.io.Closeable;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.Map.Entry;
  
  import lombok.Getter;
  import lombok.NonNull;
  import lombok.Setter;
  import lombok.val;
  
  import com.gameminers.glasspane.internal.GlassPaneMod;
  import com.google.common.collect.Lists;
  import com.google.common.collect.Maps;
  
  import net.minecraftforge.fml.common.gameevent.TickEvent.Phase;
  
  
  /**
   * Implements a class that can ease values in any object.<br/>
   * <br/>
   * "But Aesen, why not use Trident?"<br/>
   * Trident is too damn complicated, so I implemented my own, super easy to use, reflection-based easer built for use in Forge.<br/>
   * <br/>
   * Implements Closeable because it adds itself to an external map for ticking.
   * 
   * @author Aesen Vismea
   * 
   */
  // We use raw types because generics are fake anyway
  // Yes, this code is a big hack. Does it work? Yes.
  @SuppressWarnings("rawtypes")
  public class PaneEaser
  		implements Closeable {
  	protected final Object toEase;
  	protected Map<String, Byte> byteTargets = Maps.newHashMap();
  	protected Map<String, Short> shortTargets = Maps.newHashMap();
  	protected Map<String, Integer> integerTargets = Maps.newHashMap();
  	protected Map<String, Long> longTargets = Maps.newHashMap();
  	
  	
  	protected Map<String, Integer> colorTargets = Maps.newHashMap();
  	
  	
  	protected Map<String, Float> floatTargets = Maps.newHashMap();
  	protected Map<String, Double> doubleTargets = Maps.newHashMap();
  	
  	
  	protected Map<String, FieldAccessor> accessors = Maps.newHashMap();
  	
  	@Getter @Setter protected double speed = 4D;
  	@Getter @Setter protected boolean autoClose;
  	
  	protected boolean closed = false;
  	
  	protected List<Runnable> closeListeners = Lists.newArrayList();
  	
  	
  	public PaneEaser(@NonNull Object toEase) {
  		this.toEase = toEase;
  		GlassPaneMod.easers.put(toEase, this);
  	}
  	
  	@SuppressWarnings("unchecked")
  	private <T extends Number> void ease(Iterator<Entry<String, T>> iter, Class<?> primitive) {
  		while (iter.hasNext()) {
  			Entry<String, T> en = iter.next();
  			FieldAccessor<T> accessor = getAccessor(en.getKey(), primitive);
  			T current = accessor.get();
  			T val = (T) numerfy(adjust(current.doubleValue(), en.getValue().doubleValue()), current.getClass());
  			if (current.equals(val)) {
  				iter.remove();
  			}
  			accessor.set(val);
  		}
  	}
  	
  	private Number numerfy(double val, Class<? extends Number> clazz) {
  		if (clazz == Byte.class)
  			return Byte.valueOf((byte) val);
  		else if (clazz == Short.class)
  			return Short.valueOf((short) val);
  		else if (clazz == Integer.class)
  			return Integer.valueOf((int) val);
  		else if (clazz == Long.class)
  			return Long.valueOf((long) val);
  		else if (clazz == Float.class)
  			return Float.valueOf((float) val);
  		else if (clazz == Double.class) return Double.valueOf(val);
  		return null;
  	}
  	
  	@SuppressWarnings("unchecked")
  	public void onTick(Phase phase) {
  		if (closed) return;
  		if (phase == Phase.START) {
  			ease(byteTargets.entrySet().iterator(), byte.class);
  			ease(shortTargets.entrySet().iterator(), short.class);
  			ease(integerTargets.entrySet().iterator(), int.class);
  			ease(longTargets.entrySet().iterator(), long.class);
  			ease(floatTargets.entrySet().iterator(), float.class);
  			ease(doubleTargets.entrySet().iterator(), double.class);
  			{
  				Iterator<Entry<String, Integer>> iter = colorTargets.entrySet().iterator();
  				while (iter.hasNext()) {
  					val en = iter.next();
  					FieldAccessor<Integer> accessor = getAccessor(en.getKey(), int.class);
  					val current = accessor.get();
  					if (current.equals(en.getValue())) {
  						iter.remove();
  					} else {
  						Color targetCol = new Color(en.getValue(), true);
  						Color col = new Color(current, true);
  						float r = (float) Math.min(255, adjust(col.getRed(), targetCol.getRed()));
  						float g = (float) Math.min(255, adjust(col.getGreen(), targetCol.getGreen()));
  						float b = (float) Math.min(255, adjust(col.getBlue(), targetCol.getBlue()));
  						float a = (float) Math.min(255, adjust(col.getAlpha(), targetCol.getAlpha()));
  						accessor.set(new Color(r / 255f, g / 255f, b / 255f, a / 255f).getRGB());
  					}
  				}
  			}
  		} else {
  			if (autoClose && byteTargets.isEmpty() && shortTargets.isEmpty() && integerTargets.isEmpty()
  					&& longTargets.isEmpty() && floatTargets.isEmpty() && doubleTargets.isEmpty()
  					&& colorTargets.isEmpty()) {
  				close();
  			}
  		}
  	}
  	
  	protected double adjust(double current, double target) {
  		double adjustment = target - current;
  		if (adjustment > 0.05) {
  			adjustment = Math.max(0.05, adjustment / speed);
  		} else if (adjustment < -0.05) {
  			adjustment = Math.min(-0.05, adjustment / speed);
  		}
  		return current + adjustment;
  	}
  	
  	@SuppressWarnings("unchecked")
  	protected FieldAccessor getAccessor(String key, Class<?> setterClass) {
  		if (!accessors.containsKey(key)) {
  			accessors.put(key, new FriendlyFieldAccessor(toEase, toEase.getClass(), setterClass, key));
  		}
  		return accessors.get(key);
  	}
  	
  	public void setAccessor(String value, FieldAccessor<?> accessor) {
  		accessors.put(value, accessor);
  	}
  	
  	public void easeByte(String value, byte target) {
  		byteTargets.put(value, target);
  	}
  	
  	public void easeShort(String value, short target) {
  		shortTargets.put(value, target);
  	}
  	
  	public void easeInteger(String value, int target) {
  		integerTargets.put(value, target);
  	}
  	
  	public void easeLong(String value, long target) {
  		longTargets.put(value, target);
  	}
  	
  	public void easeColorInt(String value, int target) {
  		colorTargets.put(value, target);
  	}
  	
  	public void easeFloat(String value, float target) {
  		floatTargets.put(value, target);
  	}
  	
  	public void easeDouble(String value, double target) {
  		doubleTargets.put(value, target);
  	}
  	
  	public void cancelEase(String value) {
  		byteTargets.remove(value);
  		shortTargets.remove(value);
  		integerTargets.remove(value);
  		longTargets.remove(value);
  		
  		floatTargets.remove(value);
  		doubleTargets.remove(value);
  		colorTargets.remove(value);
  	}
  	
  	public void registerCloseListener(Runnable r) {
  		closeListeners.add(r);
  	}
  	
  	public void unregisterCloseListener(Runnable r) {
  		closeListeners.remove(r);
  	}
  	
  	@Override
  	public void close() {
  