					@Override
					public void run() {
						outerLoop:
						while (true) {
							if (thread != Thread.currentThread()) {
								//If it's a different thread, kill it.
								return;
							}

							List<MCVehicle> vehicles = null;
							try {
								vehicles = Static.getVehicles();
							} catch (ConcurrentModificationException ex) {
								continue outerLoop;
							}

							for (final MCVehicle v : vehicles) {
								//We need to loop through all the thresholds
								//and see if any of the points meet them. If so,
								//we know we need to fire the event. If none of them
								//match, carry on with the next vehicle. As soon as
								//one matches though, we can't quit the loop, because
								//we have to set all the thresholds.
								thresholdLoop:
								for (Integer i : thresholdList) {
									if (thresholds.containsKey(i) && thresholds.get(i).containsKey(v.getEntityId())) {
										final MCLocation last = thresholds.get(i).get(v.getEntityId());
										final MCLocation current = ((MCEntity) v).asyncGetLocation();
										if (!v.getWorld().getName().equals(last.getWorld().getName())) {
											//They moved worlds. simply put their new location in here, then
											//continue.
											thresholds.get(i).put(v.getEntityId(), v.getLocation());
											continue thresholdLoop;
										}
										Point3D lastPoint = new Point3D(last.getX(), last.getY(), last.getZ());
										Point3D currentPoint = new Point3D(current.getX(), current.getY(), current.getZ());
										double distance = lastPoint.distance(currentPoint);
										if (distance > i) {
											//We've met the threshold.
											//Well, we're still not sure. To run the prefilters on this thread,
											//we're gonna simulate a prefilter match now. We have to run this manually,
											//because each bind could have a different threshold, and it will be expecting
											//THIS from location. Other binds will be expecting other from locations.
											final MCVehicleMoveEvent fakeEvent = new MCVehicleMoveEvent() {
												boolean cancelled = false;

												@Override
												public MCLocation getFrom() {
													return last;
												}

												@Override
												public MCLocation getTo() {
													return current;
												}

												@Override
												public Object _GetObject() {
													return null;
												}

												@Override
												public void setCancelled(boolean state) {
													cancelled = state;
												}

												@Override
												public boolean isCancelled() {
													return cancelled;
												}

												@Override
												public MCVehicle getVehicle() {
													return v;
												}
											};
											//We need to run the prefilters on this thread, so we have
											//to do this all by hand.
											final SortedSet<BoundEvent> toRun = EventUtils.GetMatchingEvents(Driver.VEHICLE_MOVE, vehicle_move.this.getName(), fakeEvent, vehicle_move.this);
											//Ok, now the events to be run need to actually be run on the main server thread, so let's run that now.
											try {
												StaticLayer.GetConvertor().runOnMainThreadAndWait(new Callable<Object>() {
													@Override
													public Object call() throws Exception {
														EventUtils.FireListeners(toRun, vehicle_move.this, fakeEvent);
														return null;
													}
												});
											} catch (Exception ex) {
												Logger.getLogger(VehicleEvents.class.getName()).log(Level.SEVERE, null, ex);
											}
											if (fakeEvent.isCancelled()) {
												//Put them back at the from location
												v.teleport(last);
											} else {
												thresholds.get(i).put(v.getEntityId(), current);
											}
										}
									} else {
										//If there is no location here, just put the current location in there.
										if (!thresholds.containsKey(i)) {
											Map<Integer, MCLocation> map = new HashMap<>();
											thresholds.put(i, map);
										}
										thresholds.get(i).put(v.getEntityId(), v.asyncGetLocation());
									}
								}
							}
							synchronized (vehicle_move.this) {
								try {
									//Throttle this thread just a little
									vehicle_move.this.wait(10);
								} catch (InterruptedException ex) {
									//
								}
							}
						}
					}

					@Override
					public void run() {
						outerLoop:
						while (true) {
							if (thread != Thread.currentThread()) {
								//If it's a different thread, kill it.
								return;
							}

							List<MCVehicle> vehicles = null;
							try {
								vehicles = Static.getVehicles();
							} catch (ConcurrentModificationException ex) {
								continue outerLoop;
							}

							for (final MCVehicle v : vehicles) {
								//We need to loop through all the thresholds
								//and see if any of the points meet them. If so,
								//we know we need to fire the event. If none of them
								//match, carry on with the next vehicle. As soon as
								//one matches though, we can't quit the loop, because
								//we have to set all the thresholds.
								thresholdLoop:
								for (Integer i : thresholdList) {
									if (thresholds.containsKey(i) && thresholds.get(i).containsKey(v.getEntityId())) {
										final MCLocation last = thresholds.get(i).get(v.getEntityId());
										final MCLocation current = ((MCEntity) v).asyncGetLocation();
										if (!v.getWorld().getName().equals(last.getWorld().getName())) {
											//They moved worlds. simply put their new location in here, then
											//continue.
											thresholds.get(i).put(v.getEntityId(), v.getLocation());
											continue thresholdLoop;
										}
										Point3D lastPoint = new Point3D(last.getX(), last.getY(), last.getZ());
										Point3D currentPoint = new Point3D(current.getX(), current.getY(), current.getZ());
										double distance = lastPoint.distance(currentPoint);
										if (distance > i) {
											//We've met the threshold.
											//Well, we're still not sure. To run the prefilters on this thread,
											//we're gonna simulate a prefilter match now. We have to run this manually,
											//because each bind could have a different threshold, and it will be expecting
											//THIS from location. Other binds will be expecting other from locations.
											final MCVehicleMoveEvent fakeEvent = new MCVehicleMoveEvent() {
												boolean cancelled = false;

												@Override
												public MCLocation getFrom() {
													return last;
												}

												@Override
												public MCLocation getTo() {
													return current;
												}

												@Override
												public Object _GetObject() {
													return null;
												}

												@Override
												public void setCancelled(boolean state) {
													cancelled = state;
												}

												@Override
												public boolean isCancelled() {
													return cancelled;
												}

												@Override
												public MCVehicle getVehicle() {
													return v;
												}
											};
											//We need to run the prefilters on this thread, so we have
											//to do this all by hand.
											final SortedSet<BoundEvent> toRun = EventUtils.GetMatchingEvents(Driver.VEHICLE_MOVE, vehicle_move.this.getName(), fakeEvent, vehicle_move.this);
											//Ok, now the events to be run need to actually be run on the main server thread, so let's run that now.
											try {
												StaticLayer.GetConvertor().runOnMainThreadAndWait(new Callable<Object>() {
													@Override
													public Object call() throws Exception {
														EventUtils.FireListeners(toRun, vehicle_move.this, fakeEvent);
														return null;
													}
												});
											} catch (Exception ex) {
												Logger.getLogger(VehicleEvents.class.getName()).log(Level.SEVERE, null, ex);
											}
											if (fakeEvent.isCancelled()) {
												//Put them back at the from location
												v.teleport(last);
											} else {
												thresholds.get(i).put(v.getEntityId(), current);
											}
										}
									} else {
										//If there is no location here, just put the current location in there.
										if (!thresholds.containsKey(i)) {
											Map<Integer, MCLocation> map = new HashMap<Integer, MCLocation>();
											thresholds.put(i, map);
										}
										thresholds.get(i).put(v.getEntityId(), v.asyncGetLocation());
									}
								}
							}
							synchronized (vehicle_move.this) {
								try {
									//Throttle this thread just a little
									vehicle_move.this.wait(10);
								} catch (InterruptedException ex) {
									//
								}
							}
						}
					}

Replace Generic With Diamond HashMap<Integer,MCLocation> with HashMap<> in method public run() : void from class com.laytonsmith.core.events.drivers.VehicleEvents.vehicle_move.bind.new Thread.new Runnable


		@Override
		public void bind(BoundEvent event) {
			Map<String, Construct> prefilters = event.getPrefilter();
			if (prefilters.containsKey("threshold")) {
				int i = Static.getInt32(prefilters.get("threshold"), Target.UNKNOWN);
				thresholdList.add(i);
			}
			if (thread == null) {
				thresholdList.clear();
				thresholdList.add(1);
				thread = new Thread(new Runnable() {
					@Override
					public void run() {
						outerLoop:
						while (true) {
							if (thread != Thread.currentThread()) {
								//If it's a different thread, kill it.
								return;
							}

							List<MCVehicle> vehicles = null;
							try {
								vehicles = Static.getVehicles();
							} catch (ConcurrentModificationException ex) {
								continue outerLoop;
							}

							for (final MCVehicle v : vehicles) {
								//We need to loop through all the thresholds
								//and see if any of the points meet them. If so,
								//we know we need to fire the event. If none of them
								//match, carry on with the next vehicle. As soon as
								//one matches though, we can't quit the loop, because
								//we have to set all the thresholds.
								thresholdLoop:
								for (Integer i : thresholdList) {
									if (thresholds.containsKey(i) && thresholds.get(i).containsKey(v.getEntityId())) {
										final MCLocation last = thresholds.get(i).get(v.getEntityId());
										final MCLocation current = ((MCEntity) v).asyncGetLocation();
										if (!v.getWorld().getName().equals(last.getWorld().getName())) {
											//They moved worlds. simply put their new location in here, then
											//continue.
											thresholds.get(i).put(v.getEntityId(), v.getLocation());
											continue thresholdLoop;
										}
										Point3D lastPoint = new Point3D(last.getX(), last.getY(), last.getZ());
										Point3D currentPoint = new Point3D(current.getX(), current.getY(), current.getZ());
										double distance = lastPoint.distance(currentPoint);
										if (distance > i) {
											//We've met the threshold.
											//Well, we're still not sure. To run the prefilters on this thread,
											//we're gonna simulate a prefilter match now. We have to run this manually,
											//because each bind could have a different threshold, and it will be expecting
											//THIS from location. Other binds will be expecting other from locations.
											final MCVehicleMoveEvent fakeEvent = new MCVehicleMoveEvent() {
												boolean cancelled = false;

												@Override
												public MCLocation getFrom() {
													return last;
												}

												@Override
												public MCLocation getTo() {
													return current;
												}

												@Override
												public Object _GetObject() {
													return null;
												}

												@Override
												public void setCancelled(boolean state) {
													cancelled = state;
												}

												@Override
												public boolean isCancelled() {
													return cancelled;
												}

												@Override
												public MCVehicle getVehicle() {
													return v;
												}
											};
											//We need to run the prefilters on this thread, so we have
											//to do this all by hand.
											final SortedSet<BoundEvent> toRun = EventUtils.GetMatchingEvents(Driver.VEHICLE_MOVE, vehicle_move.this.getName(), fakeEvent, vehicle_move.this);
											//Ok, now the events to be run need to actually be run on the main server thread, so let's run that now.
											try {
												StaticLayer.GetConvertor().runOnMainThreadAndWait(new Callable<Object>() {
													@Override
													public Object call() throws Exception {
														EventUtils.FireListeners(toRun, vehicle_move.this, fakeEvent);
														return null;
													}
												});
											} catch (Exception ex) {
												Logger.getLogger(VehicleEvents.class.getName()).log(Level.SEVERE, null, ex);
											}
											if (fakeEvent.isCancelled()) {
												//Put them back at the from location
												v.teleport(last);
											} else {
												thresholds.get(i).put(v.getEntityId(), current);
											}
										}
									} else {
										//If there is no location here, just put the current location in there.
										if (!thresholds.containsKey(i)) {
											Map<Integer, MCLocation> map = new HashMap<>();
											thresholds.put(i, map);
										}
										thresholds.get(i).put(v.getEntityId(), v.asyncGetLocation());
									}
								}
							}
							synchronized (vehicle_move.this) {
								try {
									//Throttle this thread just a little
									vehicle_move.this.wait(10);
								} catch (InterruptedException ex) {
									//
								}
							}
						}
					}
				}, Implementation.GetServerType().getBranding() + "VehicleMoveEventRunner");
				thread.start();
				StaticLayer.GetConvertor().addShutdownHook(new Runnable() {
					@Override
					public void run() {
						thread = null;
					}
				});
			}
		}

		@Override
		public void bind(BoundEvent event) {
			Map<String, Construct> prefilters = event.getPrefilter();
			if (prefilters.containsKey("threshold")) {
				int i = Static.getInt32(prefilters.get("threshold"), Target.UNKNOWN);
				thresholdList.add(i);
			}
			if (thread == null) {
				thresholdList.clear();
				thresholdList.add(1);
				thread = new Thread(new Runnable() {
					@Override
					public void run() {
						outerLoop:
						while (true) {
							if (thread != Thread.currentThread()) {
								//If it's a different thread, kill it.
								return;
							}

							List<MCVehicle> vehicles = null;
							try {
								vehicles = Static.getVehicles();
							} catch (ConcurrentModificationException ex) {
								continue outerLoop;
							}

							for (final MCVehicle v : vehicles) {
								//We need to loop through all the thresholds
								//and see if any of the points meet them. If so,
								//we know we need to fire the event. If none of them
								//match, carry on with the next vehicle. As soon as
								//one matches though, we can't quit the loop, because
								//we have to set all the thresholds.
								thresholdLoop:
								for (Integer i : thresholdList) {
									if (thresholds.containsKey(i) && thresholds.get(i).containsKey(v.getEntityId())) {
										final MCLocation last = thresholds.get(i).get(v.getEntityId());
										final MCLocation current = ((MCEntity) v).asyncGetLocation();
										if (!v.getWorld().getName().equals(last.getWorld().getName())) {
											//They moved worlds. simply put their new location in here, then
											//continue.
											thresholds.get(i).put(v.getEntityId(), v.getLocation());
											continue thresholdLoop;
										}
										Point3D lastPoint = new Point3D(last.getX(), last.getY(), last.getZ());
										Point3D currentPoint = new Point3D(current.getX(), current.getY(), current.getZ());
										double distance = lastPoint.distance(currentPoint);
										if (distance > i) {
											//We've met the threshold.
											//Well, we're still not sure. To run the prefilters on this thread,
											//we're gonna simulate a prefilter match now. We have to run this manually,
											//because each bind could have a different threshold, and it will be expecting
											//THIS from location. Other binds will be expecting other from locations.
											final MCVehicleMoveEvent fakeEvent = new MCVehicleMoveEvent() {
												boolean cancelled = false;

												@Override
												public MCLocation getFrom() {
													return last;
												}

												@Override
												public MCLocation getTo() {
													return current;
												}

												@Override
												public Object _GetObject() {
													return null;
												}

												@Override
												public void setCancelled(boolean state) {
													cancelled = state;
												}

												@Override
												public boolean isCancelled() {
													return cancelled;
												}

												@Override
												public MCVehicle getVehicle() {
													return v;
												}
											};
											//We need to run the prefilters on this thread, so we have
											//to do this all by hand.
											final SortedSet<BoundEvent> toRun = EventUtils.GetMatchingEvents(Driver.VEHICLE_MOVE, vehicle_move.this.getName(), fakeEvent, vehicle_move.this);
											//Ok, now the events to be run need to actually be run on the main server thread, so let's run that now.
											try {
												StaticLayer.GetConvertor().runOnMainThreadAndWait(new Callable<Object>() {
													@Override
													public Object call() throws Exception {
														EventUtils.FireListeners(toRun, vehicle_move.this, fakeEvent);
														return null;
													}
												});
											} catch (Exception ex) {
												Logger.getLogger(VehicleEvents.class.getName()).log(Level.SEVERE, null, ex);
											}
											if (fakeEvent.isCancelled()) {
												//Put them back at the from location
												v.teleport(last);
											} else {
												thresholds.get(i).put(v.getEntityId(), current);
											}
										}
									} else {
										//If there is no location here, just put the current location in there.
										if (!thresholds.containsKey(i)) {
											Map<Integer, MCLocation> map = new HashMap<Integer, MCLocation>();
											thresholds.put(i, map);
										}
										thresholds.get(i).put(v.getEntityId(), v.asyncGetLocation());
									}
								}
							}
							synchronized (vehicle_move.this) {
								try {
									//Throttle this thread just a little
									vehicle_move.this.wait(10);
								} catch (InterruptedException ex) {
									//
								}
							}
						}
					}
				}, Implementation.GetServerType().getBranding() + "VehicleMoveEventRunner");
				thread.start();
				StaticLayer.GetConvertor().addShutdownHook(new Runnable() {
					@Override
					public void run() {
						thread = null;
					}
				});
			}
		}

Replace Generic With Diamond HashMap<Integer,MCLocation> with HashMap<> in method public bind(event BoundEvent) : void from class com.laytonsmith.core.events.drivers.VehicleEvents.vehicle_move


		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			PersistenceNetwork p = environment.getEnv(GlobalEnv.class).GetPersistenceNetwork();
			List<String> keyChain = new ArrayList<>();
			keyChain.add("storage");
			String namespace = GetNamespace(args, null, getName(), t);
			CHLog.GetLogger().Log(CHLog.Tags.PERSISTENCE, LogLevel.DEBUG, "Getting all values from " + namespace, t);
			keyChain.addAll(Arrays.asList(namespace.split("\\.")));
			Map<String[], String> list;
			try {
				list = p.getNamespace(keyChain.toArray(new String[keyChain.size()]));
			} catch (DataSourceException ex) {
				throw new ConfigRuntimeException(ex.getMessage(), ExceptionType.IOException, t, ex);
			} catch(IllegalArgumentException e){
				throw new ConfigRuntimeException(e.getMessage(), ExceptionType.FormatException, t, e);
			}
			CArray ca = new CArray(t);
			CHLog.GetLogger().Log(CHLog.Tags.PERSISTENCE, LogLevel.DEBUG, list.size() + " value(s) are being returned", t);
			for (String[] e : list.keySet()) {
				try {
					String key = StringUtils.Join(e, ".").replaceFirst("storage\\.", ""); //Get that junk out of here
					ca.set(new CString(key, t),
							Construct.json_decode(list.get(e), t), t);
				} catch (MarshalException ex) {
					Logger.getLogger(Persistence.class.getName()).log(Level.SEVERE, null, ex);
				}
			}
			return ca;
		}

		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			PersistenceNetwork p = environment.getEnv(GlobalEnv.class).GetPersistenceNetwork();
			List<String> keyChain = new ArrayList<String>();
			keyChain.add("storage");
			String namespace = GetNamespace(args, null, getName(), t);
			CHLog.GetLogger().Log(CHLog.Tags.PERSISTENCE, LogLevel.DEBUG, "Getting all values from " + namespace, t);
			keyChain.addAll(Arrays.asList(namespace.split("\\.")));
			Map<String[], String> list;
			try {
				list = p.getNamespace(keyChain.toArray(new String[keyChain.size()]));
			} catch (DataSourceException ex) {
				throw new ConfigRuntimeException(ex.getMessage(), ExceptionType.IOException, t, ex);
			} catch(IllegalArgumentException e){
				throw new ConfigRuntimeException(e.getMessage(), ExceptionType.FormatException, t, e);
			}
			CArray ca = new CArray(t);
			CHLog.GetLogger().Log(CHLog.Tags.PERSISTENCE, LogLevel.DEBUG, list.size() + " value(s) are being returned", t);
			for (String[] e : list.keySet()) {
				try {
					String key = StringUtils.Join(e, ".").replaceFirst("storage\\.", ""); //Get that junk out of here
					ca.set(new CString(key, t),
							Construct.json_decode(list.get(e), t), t);
				} catch (MarshalException ex) {
					Logger.getLogger(Persistence.class.getName()).log(Level.SEVERE, null, ex);
				}
			}
			return ca;
		}

Replace Generic With Diamond ArrayList<String> with ArrayList<> in method public exec(t Target, environment Environment, args Construct...) : Construct from class com.laytonsmith.core.functions.Persistence.get_values


		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			String namespace = GetNamespace(args, null, getName(), t);
			CHLog.GetLogger().Log(CHLog.Tags.PERSISTENCE, LogLevel.DEBUG, "Clearing value: " + namespace, t);
			try {
				environment.getEnv(GlobalEnv.class).GetPersistenceNetwork().clearKey(environment.getEnv(GlobalEnv.class).GetDaemonManager(), ("storage." + namespace).split("\\."));
			} catch (DataSourceException | ReadOnlyException | IOException ex) {
				throw new ConfigRuntimeException(ex.getMessage(), ExceptionType.IOException, t, ex);
			} catch(IllegalArgumentException e){
				throw new ConfigRuntimeException(e.getMessage(), ExceptionType.FormatException, t, e);
			}
			return CVoid.VOID;
		}

		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			String namespace = GetNamespace(args, null, getName(), t);
			CHLog.GetLogger().Log(CHLog.Tags.PERSISTENCE, LogLevel.DEBUG, "Clearing value: " + namespace, t);
			try {
				environment.getEnv(GlobalEnv.class).GetPersistenceNetwork().clearKey(environment.getEnv(GlobalEnv.class).GetDaemonManager(), ("storage." + namespace).split("\\."));
			} catch (DataSourceException ex) {
				throw new ConfigRuntimeException(ex.getMessage(), ExceptionType.IOException, t, ex);
			} catch (ReadOnlyException ex) {
				throw new ConfigRuntimeException(ex.getMessage(), ExceptionType.IOException, t, ex);
			} catch (IOException ex) {
				throw new ConfigRuntimeException(ex.getMessage(), ExceptionType.IOException, t, ex);
			} catch(IllegalArgumentException e){
				throw new ConfigRuntimeException(e.getMessage(), ExceptionType.FormatException, t, e);
			}
			return CVoid.VOID;
		}

Merge Catch [catch(DataSourceException ex), catch(ReadOnlyException ex), catch(IOException ex)] to catch(DataSourceException|ReadOnlyException|IOException ex) in method public exec(t Target, environment Environment, args Construct...) : Construct from class com.laytonsmith.core.functions.Persistence.clear_value


	/**
	 * Returns the documentation for this function that is provided as an external resource.
	 * This is useful for functions that have especially long or complex documentation, and adding
	 * it as a string directly in code would be cumbersome. To facilitate dynamic docs, templates
	 * can be provided, which will be replaced for you.
	 * @param map
	 * @return
	 */
	protected String getBundledDocs(Map<String, DocGenTemplates.Generator> map){
		String template = StreamUtils.GetString(AbstractFunction.class.getResourceAsStream("/functionDocs/" + getName()));
		if(map == null){
			map = new HashMap<>();
		}
		return DocGenTemplates.DoTemplateReplacement(template, map);
	}

	/**
	 * Returns the documentation for this function that is provided as an external resource.
	 * This is useful for functions that have especially long or complex documentation, and adding
	 * it as a string directly in code would be cumbersome. To facilitate dynamic docs, templates
	 * can be provided, which will be replaced for you.
	 * @param map
	 * @return
	 */
	protected String getBundledDocs(Map<String, DocGenTemplates.Generator> map){
		String template = StreamUtils.GetString(AbstractFunction.class.getResourceAsStream("/functionDocs/" + getName()));
		if(map == null){
			map = new HashMap<String, DocGenTemplates.Generator>();
		}
		return DocGenTemplates.DoTemplateReplacement(template, map);
	}

Replace Generic With Diamond HashMap<String,DocGenTemplates.Generator> with HashMap<> in method protected getBundledDocs(map Map<String,DocGenTemplates.Generator>) : String from class com.laytonsmith.core.functions.AbstractFunction


		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			try {
				Profiles.Profile profile;
				if (args[0] instanceof CArray) {
					Map<String, String> data = new HashMap<>();
					for (String key : ((CArray) args[0]).stringKeySet()) {
						data.put(key, ((CArray) args[0]).get(key).val());
					}
					profile = Profiles.getProfile(data);
				} else {
					Profiles profiles = environment.getEnv(GlobalEnv.class).getSQLProfiles();
					profile = profiles.getProfileById(args[0].val());
				}
				String query = args[1].val();
				Construct[] params = new Construct[args.length - 2];
				for (int i = 2; i < args.length; i++) {
					int index = i - 2;
					params[index] = args[i];
					if(params[index] instanceof CNull){
						params[index] = null;
					}
				}
				//Parameters are now all parsed into java objects.
				Connection conn = DriverManager.getConnection(profile.getConnectionString());
				try (PreparedStatement ps = conn.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) {
					for (int i = 0; i < params.length; i++) {
						int type = ps.getParameterMetaData().getParameterType(i + 1);
						if (params[i] == null) {
							if (ps.getParameterMetaData().isNullable(i + 1) == ParameterMetaData.parameterNoNulls) {
								throw new ConfigRuntimeException("Parameter " + (i + 1) + " cannot be set to null. Check your parameters and try again.", ExceptionType.SQLException, t);
							} else {
								ps.setNull(i + 1, type);
								continue;
							}
						}
						try {
							if (params[i] instanceof CInt) {
								ps.setLong(i + 1, Static.getInt(params[i], t));
							} else if (params[i] instanceof CDouble) {
								ps.setDouble(i + 1, (Double) Static.getDouble(params[i], t));
							} else if (params[i] instanceof CString) {
								ps.setString(i + 1, (String) params[i].val());
							} else if (params[i] instanceof CByteArray) {
								ps.setBytes(i + 1, ((CByteArray) params[i]).asByteArrayCopy());
							} else if (params[i] instanceof CBoolean) {
								ps.setBoolean(i + 1, Static.getBoolean(params[i]));
							}else{
								throw new ConfigRuntimeException("The type " + params[i].getClass().getSimpleName()
										+ " of parameter " + (i + 1) + " is not supported."
										, ExceptionType.CastException, t);
							}
						} catch (ClassCastException ex) {
							throw new ConfigRuntimeException("Could not cast parameter " + (i + 1) + " to "
									+ ps.getParameterMetaData().getParameterTypeName(i + 1) + " from "
									+ params[i].getClass().getSimpleName() + "."
									, ExceptionType.CastException, t, ex);
						}
					}
					boolean isResultSet = ps.execute();
					if (isResultSet) {
						//Result set
						CArray ret = new CArray(t);
						ResultSetMetaData md = ps.getMetaData();
						ResultSet rs = ps.getResultSet();
						while (rs.next()) {
							CArray row = new CArray(t);
							for (int i = 1; i <= md.getColumnCount(); i++) {
								Construct value;
								int columnType = md.getColumnType(i);
								if(rs.wasNull()){
									// Since mscript can assign null to primitives, we
									// can set it to null regardless of the data type.
									value = new CNull(t);
								} else if (columnType == Types.INTEGER
										|| columnType == Types.TINYINT
										|| columnType == Types.SMALLINT
										|| columnType == Types.BIGINT) {
									value = new CInt(rs.getLong(i), t);
								} else if (columnType == Types.FLOAT
										|| columnType == Types.DOUBLE
										|| columnType == Types.REAL
										|| columnType == Types.DECIMAL
										|| columnType == Types.NUMERIC) {
									value = new CDouble(rs.getDouble(i), t);
								} else if (columnType == Types.VARCHAR
										|| columnType == Types.CHAR
										|| columnType == Types.LONGVARCHAR) {
									value = new CString(rs.getString(i), t);
								} else if (columnType == Types.BLOB
										|| columnType == Types.BINARY
										|| columnType == Types.VARBINARY
										|| columnType == Types.LONGVARBINARY) {
									value = CByteArray.wrap(rs.getBytes(i), t);
								} else if (columnType == Types.DATE
										|| columnType == Types.TIME
										|| columnType == Types.TIMESTAMP) {
									if (md.getColumnTypeName(i).equals("YEAR")){
										value = new CInt(rs.getLong(i), t);
									} else {
										value = new CInt(rs.getTimestamp(i).getTime(), t);
									}
								} else if (columnType == Types.BOOLEAN
										|| columnType == Types.BIT) {
									value = new CBoolean(rs.getBoolean(i), t);
								} else {
									throw new ConfigRuntimeException("SQL returned a unhandled column type "
											+ md.getColumnTypeName(i) + " for column " + md.getColumnName(i) + "."
											, ExceptionType.CastException, t);
								}
								row.set(md.getColumnName(i), value, t);
							}
							ret.push(row);
						}
						return ret;
					} else {
						ResultSet rs = ps.getGeneratedKeys();
						if (rs.next()) {
						//This was an insert or something that returned generated keys. So we return
							//that here.
							return new CInt(rs.getInt(1), t);
						}
						//Update count. Just return null.
						return new CNull(t);
					}
				} finally {
					conn.close();
				}
			} catch (Profiles.InvalidProfileException | SQLException ex) {
				throw new ConfigRuntimeException(ex.getMessage(), ExceptionType.SQLException, t, ex);
			}
		}

		@Override
		public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
			try {
				Profiles.Profile profile;
				if (args[0] instanceof CArray) {
					Map<String, String> data = new HashMap<String, String>();
					for (String key : ((CArray) args[0]).stringKeySet()) {
						data.put(key, ((CArray) args[0]).get(key).val());
					}
					profile = Profiles.getProfile(data);
				} else {
					Profiles profiles = environment.getEnv(GlobalEnv.class).getSQLProfiles();
					profile = profiles.getProfileById(args[0].val());
				}
				String query = args[1].val();
				Construct[] params = new Construct[args.length - 2];
				for (int i = 2; i < args.length; i++) {
					int index = i - 2;
					params[index] = args[i];
				}
				//Parameters are now all parsed into java objects.
				Connection conn = DriverManager.getConnection(profile.getConnectionString());
				PreparedStatement ps = null;
				try {
					ps = conn.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
					for (int i = 0; i < params.length; i++) {
						int type = ps.getParameterMetaData().getParameterType(i + 1);
						if (params[i] == null) {
							if (ps.getParameterMetaData().isNullable(i + 1) == ParameterMetaData.parameterNoNulls) {
								throw new ConfigRuntimeException("Parameter " + (i + 1) + " cannot be set to null. Check your parameters and try again.", ExceptionType.SQLException, t);
							} else {
								ps.setNull(i + 1, type);
								continue;
							}
						}
						try {
							if (params[i] instanceof CInt) {
								ps.setLong(i + 1, Static.getInt(params[i], t));
							} else if (params[i] instanceof CDouble) {
								ps.setDouble(i + 1, (Double) Static.getDouble(params[i], t));
							} else if (params[i] instanceof CString) {
								ps.setString(i + 1, (String) params[i].val());
							} else if (params[i] instanceof CByteArray) {
								ps.setBytes(i + 1, ((CByteArray) params[i]).asByteArrayCopy());
							} else if (params[i] instanceof CBoolean) {
								ps.setBoolean(i + 1, Static.getBoolean(params[i]));
							}else{
								throw new ConfigRuntimeException("The type " + params[i].getClass().getSimpleName()
										+ " of parameter " + (i + 1) + " is not supported."
										, ExceptionType.CastException, t);
							}
						} catch (ClassCastException ex) {
							throw new ConfigRuntimeException("Could not cast parameter " + (i + 1) + " to "
									+ ps.getParameterMetaData().getParameterTypeName(i + 1) + " from "
									+ params[i].getClass().getSimpleName() + "."
									, ExceptionType.CastException, t, ex);
						}
					}
					boolean isResultSet = ps.execute();
					if (isResultSet) {
						//Result set
						CArray ret = new CArray(t);
						ResultSetMetaData md = ps.getMetaData();
						ResultSet rs = ps.getResultSet();
						while (rs.next()) {
							CArray row = new CArray(t);
							for (int i = 1; i <= md.getColumnCount(); i++) {
								Construct value;
								int columnType = md.getColumnType(i);
								if (columnType == Types.INTEGER
										|| columnType == Types.TINYINT
										|| columnType == Types.SMALLINT
										|| columnType == Types.BIGINT) {
									value = new CInt(rs.getLong(i), t);
								} else if (columnType == Types.FLOAT
										|| columnType == Types.DOUBLE
										|| columnType == Types.REAL
										|| columnType == Types.DECIMAL
										|| columnType == Types.NUMERIC) {
									value = new CDouble(rs.getDouble(i), t);
								} else if (columnType == Types.VARCHAR
										|| columnType == Types.CHAR
										|| columnType == Types.LONGVARCHAR) {
									value = new CString(rs.getString(i), t);
								} else if (columnType == Types.BLOB
										|| columnType == Types.BINARY
										|| columnType == Types.VARBINARY
										|| columnType == Types.LONGVARBINARY) {
									value = CByteArray.wrap(rs.getBytes(i), t);
								} else if (columnType == Types.DATE
										|| columnType == Types.TIME
										|| columnType == Types.TIMESTAMP) {
									if (md.getColumnTypeName(i).equals("YEAR")){
										value = new CInt(rs.getLong(i), t);
									} else {
										value = new CInt(rs.getTimestamp(i).getTime(), t);
									}
								} else if (columnType == Types.BOOLEAN
										|| columnType == Types.BIT) {
									value = new CBoolean(rs.getBoolean(i), t);
								} else {
									throw new ConfigRuntimeException("SQL returned a unhandled column type "
											+ md.getColumnTypeName(i) + " for column " + md.getColumnName(i) + "."
											, ExceptionType.CastException, t);
								}
								row.set(md.getColumnName(i), value, t);
							}
							ret.push(row);
						}
						return ret;
					} else {
						ResultSet rs = ps.getGeneratedKeys();
						if (rs.next()) {
						//This was an insert or something that returned generated keys. So we return
							//that here.
							return new CInt(rs.getInt(1), t);
						}
						//Update count. Just return null.
						return new CNull(t);
					}
				} finally {
					if (ps != null) {
						ps.close();
					}
					if (conn != null) {
						conn.close();
					}
				}
			} catch (Profiles.InvalidProfileException ex) {
				throw new ConfigRuntimeException(ex.getMessage(), ExceptionType.SQLException, t, ex);
			} catch (SQLException ex) {
				throw new ConfigRuntimeException(ex.getMessage(), ExceptionType.SQLException, t, ex);
			}
		}

Try With Resources try(PreparedStatement ps=conn.prepareStatement(query,Statement.RETURN_GENERATED_KEYS)) in method public exec(t Target, environment Environment, args Construct...) : Construct from class com.laytonsmith.core.functions.SQL.query


	public static void ManualTrigger(String eventName, CArray object, boolean serverWide) {
		for (Driver type : event_handles.keySet()) {
			SortedSet<BoundEvent> toRun = new TreeSet<>();
			SortedSet<BoundEvent> bounded = GetEvents(type);
			Event driver = EventList.getEvent(type, eventName);
			if (bounded != null) {
				for (BoundEvent b : bounded) {
					if (b.getEventName().equalsIgnoreCase(eventName)) {
						try {
							BindableEvent convertedEvent;
							try {
								convertedEvent = driver.convert(object);
							} catch (ConfigRuntimeException e) {
								ConfigRuntimeException.HandleUncaughtException(e, b.getEnvironment());
								continue;
							}
							if (driver.matches(b.getPrefilter(), convertedEvent)) {
								toRun.add(b);
							}
						} catch (PrefilterNonMatchException ex) {
							//Not running this one
						}
					}
				}
			}
			//If it's not a serverwide event, or this event doesn't support external events.
			if (!toRun.isEmpty()) {
				if (!serverWide || !driver.supportsExternal()) {
					FireListeners(toRun, driver, driver.convert(object));
				} else {
					//It's serverwide, so we can just trigger it normally with the driver, and it should trickle back down to us
					driver.manualTrigger(driver.convert(object));
				}
			} else {
				//They have fired a non existant event
				ConfigRuntimeException.DoWarning(ConfigRuntimeException.CreateUncatchableException("Non existant event is being triggered: " + eventName, object.getTarget()));
			}
		}
	}

	public static void ManualTrigger(String eventName, CArray object, boolean serverWide) {
		for (Driver type : event_handles.keySet()) {
			SortedSet<BoundEvent> toRun = new TreeSet<BoundEvent>();
			SortedSet<BoundEvent> bounded = GetEvents(type);
			Event driver = EventList.getEvent(type, eventName);
			if (bounded != null) {
				for (BoundEvent b : bounded) {
					if (b.getEventName().equalsIgnoreCase(eventName)) {
						try {
							BindableEvent convertedEvent;
							try {
								convertedEvent = driver.convert(object);
							} catch (ConfigRuntimeException e) {
								ConfigRuntimeException.HandleUncaughtException(e, b.getEnvironment());
								continue;
							}
							if (driver.matches(b.getPrefilter(), convertedEvent)) {
								toRun.add(b);
							}
						} catch (PrefilterNonMatchException ex) {
							//Not running this one
						}
					}
				}
			}
			//If it's not a serverwide event, or this event doesn't support external events.
			if (!toRun.isEmpty()) {
				if (!serverWide || !driver.supportsExternal()) {
					FireListeners(toRun, driver, driver.convert(object));
				} else {
					//It's serverwide, so we can just trigger it normally with the driver, and it should trickle back down to us
					driver.manualTrigger(driver.convert(object));
				}
			} else {
				//They have fired a non existant event
				ConfigRuntimeException.DoWarning(ConfigRuntimeException.CreateUncatchableException("Non existant event is being triggered: " + eventName, object.getTarget()));
			}
		}
	}

Replace Generic With Diamond TreeSet<BoundEvent> with TreeSet<> in method public ManualTrigger(eventName String, object CArray, serverWide boolean) : void from class com.laytonsmith.core.events.EventUtils


	private static CString getHMAC(String algorithm, Target t, Construct[] args) {
		try {
			SecretKeySpec signingKey = new SecretKeySpec(args[0].val().getBytes(), algorithm);
			Mac mac = Mac.getInstance(algorithm);
			mac.init(signingKey);
			byte[] hmac = mac.doFinal(args[1].val().getBytes());
			String hash = StringUtils.toHex(hmac).toLowerCase();
			return new CString(hash, t);
		} catch (NoSuchAlgorithmException | InvalidKeyException ex) {
			throw new ConfigRuntimeException("An error occured while trying to hash your data", ExceptionType.PluginInternalException, t, ex);
		}
	}

	private static CString getHMAC(String algorithm, Target t, Construct[] args) {
		try {
			SecretKeySpec signingKey = new SecretKeySpec(args[0].val().getBytes(), algorithm);
			Mac mac = Mac.getInstance(algorithm);
			mac.init(signingKey);
			byte[] hmac = mac.doFinal(args[1].val().getBytes());
			String hash = StringUtils.toHex(hmac).toLowerCase();
			return new CString(hash, t);
		} catch (NoSuchAlgorithmException ex) {
			throw new ConfigRuntimeException("An error occured while trying to hash your data", ExceptionType.PluginInternalException, t, ex);
		}  catch (InvalidKeyException ex) {
			throw new ConfigRuntimeException("An error occured while trying to hash your data", ExceptionType.PluginInternalException, t, ex);
		}
	}

Merge Catch [catch(NoSuchAlgorithmException ex), catch(InvalidKeyException ex)] to catch(NoSuchAlgorithmException|InvalidKeyException ex) in method private getHMAC(algorithm String, t Target, args Construct[]) : CString from class com.laytonsmith.core.functions.Crypto


	/**
	 * Combines finding classes with a specified annotation, and classes that extend a certain type.
	 * @param <T> The type that will be returned, based on superClass
	 * @param annotation The annotation that the classes should be tagged with
	 * @param superClass The super class that the classes should extend
	 * @return A set of class mirrors that match the criteria
	 */
	public <T> Set<ClassMirror<T>> getClassesWithAnnotationThatExtend(Class<? extends Annotation> annotation, Class<T> superClass){
		Set<ClassMirror<T>> mirrors = new HashSet<>();
		for(ClassMirror<?> c : getClassesWithAnnotation(annotation)){
			if(doesClassExtend(c, superClass)){
				mirrors.add((ClassMirror<T>)c);
			}
		}
		return mirrors;
	}

	/**
	 * Combines finding classes with a specified annotation, and classes that extend a certain type.
	 * @param <T> The type that will be returned, based on superClass
	 * @param annotation The annotation that the classes should be tagged with
	 * @param superClass The super class that the classes should extend
	 * @return A set of class mirrors that match the criteria
	 */
	public <T> Set<ClassMirror<T>> getClassesWithAnnotationThatExtend(Class<? extends Annotation> annotation, Class<T> superClass){
		Set<ClassMirror<T>> mirrors = new HashSet<ClassMirror<T>>();
		for(ClassMirror<?> c : getClassesWithAnnotation(annotation)){
			if(doesClassExtend(c, superClass)){
				mirrors.add((ClassMirror<T>)c);
			}
		}
		return mirrors;
	}

Replace Generic With Diamond HashSet<ClassMirror<T>> with HashSet<> in method public getClassesWithAnnotationThatExtend(annotation Class<? extends Annotation>, superClass Class<T>) : Set<ClassMirror<T>> from class com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery


	/**
	 * Executes a pre-compiled MethodScript, given the specified Script
	 * environment, but also provides a method to set the constants in the
	 * script.
	 *
	 * @param root
	 * @param env
	 * @param done
	 * @param script
	 * @param vars
	 * @return
	 */
	public static Construct execute(ParseTree root, Environment env, MethodScriptComplete done, Script script, List<Variable> vars) {
		if (script == null) {
			script = new Script(null, null);
		}
		if (vars != null) {
			Map<String, Variable> varMap = new HashMap<>();
			for (Variable v : vars) {
				varMap.put(v.getName(), v);
			}
			for (Construct tempNode : root.getAllData()) {
				if (tempNode instanceof Variable) {
					Variable vv = varMap.get(((Variable) tempNode).getName());
					if(vv != null){
						((Variable) tempNode).setVal(vv.getDefault());
					} else {
						//The variable is unset. I'm not quite sure what cases would cause this
						((Variable) tempNode).setVal("");
					}
				}
			}
		}
		StringBuilder b = new StringBuilder();
		Construct returnable = null;
		for (ParseTree gg : root.getChildren()) {
			script.setLabel(env.getEnv(GlobalEnv.class).GetLabel());
			Construct retc = script.eval(gg, env);
			if (root.numberOfChildren() == 1) {
				returnable = retc;
			}
			String ret = retc instanceof CNull ? "null" : retc.val();
			if (ret != null && !ret.trim().isEmpty()) {
				b.append(ret).append(" ");
			}
		}
		if (done != null) {
			done.done(b.toString().trim());
		}
		if (returnable != null) {
			return returnable;
		}
		return Static.resolveConstruct(b.toString().trim(), Target.UNKNOWN);
	}

	/**
	 * Executes a pre-compiled MethodScript, given the specified Script
	 * environment, but also provides a method to set the constants in the
	 * script.
	 *
	 * @param root
	 * @param env
	 * @param done
	 * @param script
	 * @param vars
	 * @return
	 */
	public static Construct execute(ParseTree root, Environment env, MethodScriptComplete done, Script script, List<Variable> vars) {
		if (script == null) {
			script = new Script(null, null);
		}
		if (vars != null) {
			Map<String, Variable> varMap = new HashMap<String, Variable>();
			for (Variable v : vars) {
				varMap.put(v.getName(), v);
			}
			for (Construct tempNode : root.getAllData()) {
				if (tempNode instanceof Variable) {
					Variable vv = varMap.get(((Variable) tempNode).getName());
					if(vv != null){
						((Variable) tempNode).setVal(vv.getDefault());
					} else {
						//The variable is unset. I'm not quite sure what cases would cause this
						((Variable) tempNode).setVal("");
					}
				}
			}
		}
		StringBuilder b = new StringBuilder();
		Construct returnable = null;
		for (ParseTree gg : root.getChildren()) {
			script.setLabel(env.getEnv(GlobalEnv.class).GetLabel());
			Construct retc = script.eval(gg, env);
			if (root.numberOfChildren() == 1) {
				returnable = retc;
			}
			String ret = retc instanceof CNull ? "null" : retc.val();
			if (ret != null && !ret.trim().isEmpty()) {
				b.append(ret).append(" ");
			}
		}
		if (done != null) {
			done.done(b.toString().trim());
		}
		if (returnable != null) {
			return returnable;
		}
		return Static.resolveConstruct(b.toString().trim(), Target.UNKNOWN);
	}

Replace Generic With Diamond HashMap<String,Variable> with HashMap<> in method public execute(root ParseTree, env Environment, done MethodScriptComplete, script Script, vars List<Variable>) : Construct from class com.laytonsmith.core.MethodScriptCompiler


    @Override
    public Procedure clone() throws CloneNotSupportedException {
        Procedure clone = (Procedure) super.clone();
        if (this.varList != null) {
            clone.varList = new HashMap<>(this.varList);
        }
        if (this.tree != null) {
            clone.tree = this.tree.clone();
        }
        return clone;
    }

    @Override
    public Procedure clone() throws CloneNotSupportedException {
        Procedure clone = (Procedure) super.clone();
        if (this.varList != null) {
            clone.varList = new HashMap<String, IVariable>(this.varList);
        }
        if (this.tree != null) {
            clone.tree = this.tree.clone();
        }
        return clone;
    }

Replace Generic With Diamond HashMap<String,IVariable> with HashMap<> in method public clone() : Procedure from class com.laytonsmith.core.Procedure


	/**
	 * Called on plugin enable.
	 */
	@Override
	public void onEnable() {
		if(loadingThread.isAlive()){
			System.out.println("[CommandHelper] Waiting for extension loading to complete...");

			try {
				loadingThread.join();
			} catch (InterruptedException ex) {
				Logger.getLogger(CommandHelperPlugin.class.getName()).log(Level.SEVERE, null, ex);
			}
		}

		//Metrics
		try {
			org.mcstats.Metrics m = new Metrics(this);
			m.addCustomData(new Metrics.Plotter("Player count") {

				@Override
				public int getValue() {
					return Static.getServer().getOnlinePlayers().length;
				}
			});
			m.start();
		} catch (IOException e) {
			// Failed to submit the stats :-(
		}

		try {
			//This may seem redundant, but on a /reload, we want to refresh these
			//properties.
			Prefs.init(CommandHelperFileLocations.getDefault().getPreferencesFile());
		} catch (IOException ex) {
			Logger.getLogger(CommandHelperPlugin.class.getName()).log(Level.SEVERE, null, ex);
		}
		if(Prefs.UseSudoFallback()){
			Logger.getLogger(CommandHelperPlugin.class.getName()).log(Level.WARNING, "In your preferences, use-sudo-fallback is turned on. Consider turning this off if you can.");
		}
		CHLog.initialize(CommandHelperFileLocations.getDefault().getConfigDirectory());

		version = new SimpleVersion(getDescription().getVersion());
		PermissionsResolverManager.initialize(this);
		permissionsResolver = new CommandHelperPermissionsResolver(PermissionsResolverManager.getInstance());
		Plugin pwep = getServer().getPluginManager().getPlugin("WorldEdit");
		if (pwep != null && pwep.isEnabled() && pwep instanceof WorldEditPlugin) {
			wep = (WorldEditPlugin) pwep;
		}

		String script_name = Prefs.ScriptName();
		String main_file = Prefs.MainFile();
		boolean showSplashScreen = Prefs.ShowSplashScreen();
		if (showSplashScreen) {
			System.out.println(TermColors.reset());
			//System.out.flush();
			System.out.println("\n\n\n" + Static.Logo());
		}
		ac = new AliasCore(new File(CommandHelperFileLocations.getDefault().getConfigDirectory(),
				script_name), CommandHelperFileLocations.getDefault().getLocalPackagesDirectory(),
				CommandHelperFileLocations.getDefault().getPreferencesFile(), new File(CommandHelperFileLocations.getDefault().getConfigDirectory(),
				main_file), permissionsResolver, this);
		ac.reload(null, null);

		//Clear out our hostname cache
		hostnameLookupCache = new ConcurrentHashMap<>();
		//Create a new thread pool, with a custom ThreadFactory,
		//so we can more clearly name our threads.
		hostnameLookupThreadPool = Executors.newFixedThreadPool(3, new ThreadFactory() {
			@Override
			public Thread newThread(Runnable r) {
				return new Thread(r, "CommandHelperHostnameLookup-" + (++hostnameThreadPoolID));
			}
		});
		for (MCPlayer p : Static.getServer().getOnlinePlayers()) {
			//Repopulate our cache for currently online players.
			//New players that join later will get a lookup done
			//on them at that time.
			Static.HostnameCache(p);
		}

		Static.PlayDirty();
		registerEvent(playerListener);

		//interpreter events
		registerEvent(interpreterListener);
		registerEvent(serverListener);

		//Script events
		StaticLayer.Startup(this);

		playerListener.loadGlobalAliases();
		interpreterListener.reload();

		Static.getLogger().log(Level.INFO, "[CommandHelper] CommandHelper {0} enabled", getDescription().getVersion());
	}

	/**
	 * Called on plugin enable.
	 */
	@Override
	public void onEnable() {
		if(loadingThread.isAlive()){
			System.out.println("[CommandHelper] Waiting for extension loading to complete...");

			try {
				loadingThread.join();
			} catch (InterruptedException ex) {
				Logger.getLogger(CommandHelperPlugin.class.getName()).log(Level.SEVERE, null, ex);
			}
		}

		//Metrics
		try {
			org.mcstats.Metrics m = new Metrics(this);
			m.addCustomData(new Metrics.Plotter("Player count") {

				@Override
				public int getValue() {
					return Static.getServer().getOnlinePlayers().length;
				}
			});
			m.start();
		} catch (IOException e) {
			// Failed to submit the stats :-(
		}

		try {
			//This may seem redundant, but on a /reload, we want to refresh these
			//properties.
			Prefs.init(CommandHelperFileLocations.getDefault().getPreferencesFile());
		} catch (IOException ex) {
			Logger.getLogger(CommandHelperPlugin.class.getName()).log(Level.SEVERE, null, ex);
		}
		if(Prefs.UseSudoFallback()){
			Logger.getLogger(CommandHelperPlugin.class.getName()).log(Level.WARNING, "In your preferences, use-sudo-fallback is turned on. Consider turning this off if you can.");
		}
		CHLog.initialize(CommandHelperFileLocations.getDefault().getConfigDirectory());

		version = new SimpleVersion(getDescription().getVersion());
		PermissionsResolverManager.initialize(this);
		permissionsResolver = new CommandHelperPermissionsResolver(PermissionsResolverManager.getInstance());
		Plugin pwep = getServer().getPluginManager().getPlugin("WorldEdit");
		if (pwep != null && pwep.isEnabled() && pwep instanceof WorldEditPlugin) {
			wep = (WorldEditPlugin) pwep;
		}

		String script_name = Prefs.ScriptName();
		String main_file = Prefs.MainFile();
		boolean showSplashScreen = Prefs.ShowSplashScreen();
		if (showSplashScreen) {
			System.out.println(TermColors.reset());
			//System.out.flush();
			System.out.println("\n\n\n" + Static.Logo());
		}
		ac = new AliasCore(new File(CommandHelperFileLocations.getDefault().getConfigDirectory(),
				script_name), CommandHelperFileLocations.getDefault().getLocalPackagesDirectory(),
				CommandHelperFileLocations.getDefault().getPreferencesFile(), new File(CommandHelperFileLocations.getDefault().getConfigDirectory(),
				main_file), permissionsResolver, this);
		ac.reload(null, null);

		//Clear out our hostname cache
		hostnameLookupCache = new ConcurrentHashMap<String, String>();
		//Create a new thread pool, with a custom ThreadFactory,
		//so we can more clearly name our threads.
		hostnameLookupThreadPool = Executors.newFixedThreadPool(3, new ThreadFactory() {
			@Override
			public Thread newThread(Runnable r) {
				return new Thread(r, "CommandHelperHostnameLookup-" + (++hostnameThreadPoolID));
			}
		});
		for (MCPlayer p : Static.getServer().getOnlinePlayers()) {
			//Repopulate our cache for currently online players.
			//New players that join later will get a lookup done
			//on them at that time.
			Static.HostnameCache(p);
		}

		Static.PlayDirty();
		registerEvent(playerListener);

		//interpreter events
		registerEvent(interpreterListener);
		registerEvent(serverListener);

		//Script events
		StaticLayer.Startup(this);

		playerListener.loadGlobalAliases();
		interpreterListener.reload();

		Static.getLogger().log(Level.INFO, "[CommandHelper] CommandHelper {0} enabled", getDescription().getVersion());
	}

Replace Generic With Diamond ConcurrentHashMap<String,String> with ConcurrentHashMap<> in method public onEnable() : void from class com.laytonsmith.commandhelper.CommandHelperPlugin


		@Override
		public ParseTree optimizeDynamic(Target t, List<ParseTree> children, FileOptions fileOptions) throws ConfigCompileException, ConfigRuntimeException {

			FileOptions options = new FileOptions(new HashMap<String, String>());
			if (!children.isEmpty()) {
				options = children.get(0).getFileOptions();
			}
			ParseTree node = new ParseTree(new CFunction(this.getName(), t), options);
			node.setOptimized(true);
			List<ParseTree> optimizedTree = new ArrayList<>();
			//We have to cache the return value if even if we find it, so we can check for syntax errors
			//in all the branches, not just the ones before the first hardcoded true
			ParseTree toReturn = null;
			for (int i = 0; i <= children.size() - 2; i += 2) {
				ParseTree statement = children.get(i);
				ParseTree code = children.get(i + 1);
				Construct evalStatement = statement.getData();
				if (evalStatement instanceof CIdentifier) {
					//check for an else here, if so, it's a compile error
					if (evalStatement.val().equals("else")) {
						throw new ConfigCompileException("Unexpected else", t);
					}
				}
				if (!statement.getData().isDynamic()) {
					if (evalStatement instanceof CIdentifier) {
						evalStatement = ((CIdentifier) evalStatement).contained().getData();
					}
					//If it's hardcoded true, we found it.
					if (Static.getBoolean(evalStatement)) {
						if (toReturn == null) {
							toReturn = code;
						}
					} //else it's hard coded false, and we can ignore it.
				} else {
					//It's dynamic, so we can't do anything with it
					optimizedTree.add(statement);
					optimizedTree.add(code);
				}
				// We can pull up if(@a){ if(@b){ ...} } to if(@a && @b){ ... },
				// which, in my profiling is faster. The only special consideration
				// we have to make is to ensure that the inner if is the only statement
				// in the entire block, (including lack of an else) so any code outside the inner if causes this
				// optimization to be impossible. An inner ifelse cannot be optimized, unless it only has 2 arguments
				// (in which case, it's a normal if())
				// If the outer if has an else, we can't do it either, so check that the outer if only has 2 children too.
				if (children.size() == 2 && code.getChildren().size() == 2 && code.getData() instanceof CFunction && code.getData().val().equals("ifelse")) {
					CFunction andNode = new CFunction(and, t);
					ParseTree andTree = new ParseTree(andNode, statement.getFileOptions());
					andTree.addChild(statement);
					andTree.addChild(code.getChildAt(0));
					if (optimizedTree.size() < 1) {
						optimizedTree.add(andTree);
					} else {
						optimizedTree.set(i, andTree);
					}
					if (optimizedTree.size() < 2) {
						optimizedTree.add(code.getChildAt(1));
					} else {
						optimizedTree.set(i + 1, code.getChildAt(1));
					}
					//We need to set this to re-optimize the children, because the and() construction may be unoptimal now
					for (ParseTree pt : andTree.getChildren()) {
						pt.setOptimized(false);
					}
					node.setOptimized(false);
				}
			}
			if (toReturn != null) {
				return toReturn;
			}
			if (children.size() % 2 == 1) {
				ParseTree ret = children.get(children.size() - 1);
				if (ret.getData() instanceof CIdentifier) {
					optimizedTree.add(((CIdentifier) ret.getData()).contained());
				} else {
					optimizedTree.add(ret);
				}
				if (children.size() == 1 && optimizedTree.size() == 1) {
					//Oh. Well, we can just return this node then, though we have
					//to surround it with g() so there are no side effects. However,
					//if the function itself has no side effects, we can simply remove
					//it altogether.
					if (optimizedTree.get(0).getData() instanceof CFunction) {
						Function f = ((CFunction) optimizedTree.get(0).getData()).getFunction();
						if (f instanceof Optimizable) {
							if (((Optimizable) f).optimizationOptions().contains(OptimizationOption.NO_SIDE_EFFECTS)) {
								return Optimizable.REMOVE_ME;
							}
						}
					}
					ParseTree gNode = new ParseTree(new CFunction(g, t), options);
					gNode.addChild(optimizedTree.get(0));
					return gNode;
				}
			}
			if (optimizedTree.size() == 1) {
				//The whole tree has been optimized out. Return just the element
				return optimizedTree.get(0);
			}
			node.setChildren(optimizedTree);
			if (node.getChildren().isEmpty()) {
				//We have optimized it out entirely, so remove us
				return Optimizable.REMOVE_ME;
			}
			return node;

		}

		@Override
		public ParseTree optimizeDynamic(Target t, List<ParseTree> children, FileOptions fileOptions) throws ConfigCompileException, ConfigRuntimeException {

			FileOptions options = new FileOptions(new HashMap<String, String>());
			if (!children.isEmpty()) {
				options = children.get(0).getFileOptions();
			}
			ParseTree node = new ParseTree(new CFunction(this.getName(), t), options);
			node.setOptimized(true);
			List<ParseTree> optimizedTree = new ArrayList<ParseTree>();
			//We have to cache the return value if even if we find it, so we can check for syntax errors
			//in all the branches, not just the ones before the first hardcoded true
			ParseTree toReturn = null;
			for (int i = 0; i <= children.size() - 2; i += 2) {
				ParseTree statement = children.get(i);
				ParseTree code = children.get(i + 1);
				Construct evalStatement = statement.getData();
				if (evalStatement instanceof CIdentifier) {
					//check for an else here, if so, it's a compile error
					if (evalStatement.val().equals("else")) {
						throw new ConfigCompileException("Unexpected else", t);
					}
				}
				if (!statement.getData().isDynamic()) {
					if (evalStatement instanceof CIdentifier) {
						evalStatement = ((CIdentifier) evalStatement).contained().getData();
					}
					//If it's hardcoded true, we found it.
					if (Static.getBoolean(evalStatement)) {
						if (toReturn == null) {
							toReturn = code;
						}
					} //else it's hard coded false, and we can ignore it.
				} else {
					//It's dynamic, so we can't do anything with it
					optimizedTree.add(statement);
					optimizedTree.add(code);
				}
				// We can pull up if(@a){ if(@b){ ...} } to if(@a && @b){ ... },
				// which, in my profiling is faster. The only special consideration
				// we have to make is to ensure that the inner if is the only statement
				// in the entire block, (including lack of an else) so any code outside the inner if causes this
				// optimization to be impossible. An inner ifelse cannot be optimized, unless it only has 2 arguments
				// (in which case, it's a normal if())
				// If the outer if has an else, we can't do it either, so check that the outer if only has 2 children too.
				if (children.size() == 2 && code.getChildren().size() == 2 && code.getData() instanceof CFunction && code.getData().val().equals("ifelse")) {
					CFunction andNode = new CFunction(and, t);
					ParseTree andTree = new ParseTree(andNode, statement.getFileOptions());
					andTree.addChild(statement);
					andTree.addChild(code.getChildAt(0));
					if (optimizedTree.size() < 1) {
						optimizedTree.add(andTree);
					} else {
						optimizedTree.set(i, andTree);
					}
					if (optimizedTree.size() < 2) {
						optimizedTree.add(code.getChildAt(1));
					} else {
						optimizedTree.set(i + 1, code.getChildAt(1));
					}
					//We need to set this to re-optimize the children, because the and() construction may be unoptimal now
					for (ParseTree pt : andTree.getChildren()) {
						pt.setOptimized(false);
					}
					node.setOptimized(false);
				}
			}
			if (toReturn != null) {
				return toReturn;
			}
			if (children.size() % 2 == 1) {
				ParseTree ret = children.get(children.size() - 1);
				if (ret.getData() instanceof CIdentifier) {
					optimizedTree.add(((CIdentifier) ret.getData()).contained());
				} else {
					optimizedTree.add(ret);
				}
				if (children.size() == 1 && optimizedTree.size() == 1) {
					//Oh. Well, we can just return this node then, though we have
					//to surround it with g() so there are no side effects. However,
					//if the function itself has no side effects, we can simply remove
					//it altogether.
					if (optimizedTree.get(0).getData() instanceof CFunction) {
						Function f = ((CFunction) optimizedTree.get(0).getData()).getFunction();
						if (f instanceof Optimizable) {
							if (((Optimizable) f).optimizationOptions().contains(OptimizationOption.NO_SIDE_EFFECTS)) {
								return Optimizable.REMOVE_ME;
							}
						}
					}
					ParseTree gNode = new ParseTree(new CFunction(g, t), options);
					gNode.addChild(optimizedTree.get(0));
					return gNode;
				}
			}
			if (optimizedTree.size() == 1) {
				//The whole tree has been optimized out. Return just the element
				return optimizedTree.get(0);
			}
			node.setChildren(optimizedTree);
			if (node.getChildren().isEmpty()) {
				//We have optimized it out entirely, so remove us
				return Optimizable.REMOVE_ME;
			}
			return node;

		}

Replace Generic With Diamond ArrayList<ParseTree> with ArrayList<> in method public optimizeDynamic(t Target, children List<ParseTree>, fileOptions FileOptions) : ParseTree from class com.laytonsmith.core.functions.BasicLogic.ifelse


	/* package */ AnnotationMirror(ClassReferenceMirror type, boolean visible){
		this.type = type;
		this.visible = visible;
		this.values = new ArrayList<>();
	}

	/* package */ AnnotationMirror(ClassReferenceMirror type, boolean visible){
		this.type = type;
		this.visible = visible;
		this.values = new ArrayList<AnnotationValue>();
	}

Replace Generic With Diamond ArrayList<AnnotationValue> with ArrayList<> in method package AnnotationMirror(type ClassReferenceMirror, visible boolean) from class com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.AnnotationMirror


	/* package */ FieldMirror(ModifierMirror modifiers, ClassReferenceMirror type, String name, Object value){
		super(null, modifiers, type, name);
		this.value = value;
		this.annotations = new ArrayList<>();
	}

	/* package */ FieldMirror(ModifierMirror modifiers, ClassReferenceMirror type, String name, Object value){
		super(null, modifiers, type, name);
		this.value = value;
		this.annotations = new ArrayList<AnnotationMirror>();
	}

Replace Generic With Diamond ArrayList<AnnotationMirror> with ArrayList<> in method package FieldMirror(modifiers ModifierMirror, type ClassReferenceMirror, name String, value Object) from class com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.FieldMirror


	/* package */ MethodMirror(ClassReferenceMirror parentClass, ModifierMirror modifiers, ClassReferenceMirror type,
			String name, List<ClassReferenceMirror> params, boolean isVararg, boolean isSynthetic){
		super(null, modifiers, type, name);
		annotations = new ArrayList<>();
		this.parentClass = parentClass;
		this.params = params;
		this.isVararg = isVararg;
		this.isSynthetic = isSynthetic;
	}

	/* package */ MethodMirror(ClassReferenceMirror parentClass, ModifierMirror modifiers, ClassReferenceMirror type,
			String name, List<ClassReferenceMirror> params, boolean isVararg, boolean isSynthetic){
		super(null, modifiers, type, name);
		annotations = new ArrayList<AnnotationMirror>();
		this.parentClass = parentClass;
		this.params = params;
		this.isVararg = isVararg;
		this.isSynthetic = isSynthetic;
	}

Replace Generic With Diamond ArrayList<AnnotationMirror> with ArrayList<> in method package MethodMirror(parentClass ClassReferenceMirror, modifiers ModifierMirror, type ClassReferenceMirror, name String, params List<ClassReferenceMirror>, isVararg boolean, isSynthetic boolean) from class com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.MethodMirror


	private static void setup() {
		if (methods == null) {
			methods = new HashMap<>();

			List<ClassMirror<?>> classes = ClassDiscovery.getDefaultInstance().getKnownClasses(ClassDiscovery.GetClassContainer(CheckOverrides.class));
			for (ClassMirror cm : classes) {
				Class c = cm.loadClass(CheckOverrides.class.getClassLoader(), false);
				if (c.isInterface()) {
					continue;
				}
				Set<Method> mm = getPotentiallyOverridingMethods(c);
				if (!mm.isEmpty()) {
					methods.put(c, mm);
				}
			}
		}
	}

	private static void setup() {
		if (methods == null) {
			methods = new HashMap<Class, Set<Method>>();

			List<ClassMirror<?>> classes = ClassDiscovery.getDefaultInstance().getKnownClasses(ClassDiscovery.GetClassContainer(CheckOverrides.class));
			for (ClassMirror cm : classes) {
				Class c = cm.loadClass(CheckOverrides.class.getClassLoader(), false);
				if (c.isInterface()) {
					continue;
				}
				Set<Method> mm = getPotentiallyOverridingMethods(c);
				if (!mm.isEmpty()) {
					methods.put(c, mm);
				}
			}
		}
	}

Replace Generic With Diamond HashMap<Class,Set<Method>> with HashMap<> in method private setup() : void from class com.laytonsmith.PureUtilities.Common.Annotations.CheckOverrides


	/**
	 * Returns a list of potentially overriding methods in a class. That is, the
	 * non-private, non-static methods.
	 *
	 * @param c
	 * @return
	 */
	private static Set<Method> getPotentiallyOverridingMethods(Class c) {
		Set<Method> methodList = new HashSet<>();
		for (Method m : c.getDeclaredMethods()) {
			//Ignore static or public methods, since those can't override anything
			if ((m.getModifiers() & Modifier.PRIVATE) == 0 && (m.getModifiers() & Modifier.STATIC) == 0
					&& !m.isSynthetic()) {
				methodList.add(m);
			}
		}
		return methodList;
	}

	/**
	 * Returns a list of potentially overriding methods in a class. That is, the
	 * non-private, non-static methods.
	 *
	 * @param c
	 * @return
	 */
	private static Set<Method> getPotentiallyOverridingMethods(Class c) {
		Set<Method> methodList = new HashSet<Method>();
		for (Method m : c.getDeclaredMethods()) {
			//Ignore static or public methods, since those can't override anything
			if ((m.getModifiers() & Modifier.PRIVATE) == 0 && (m.getModifiers() & Modifier.STATIC) == 0
					&& !m.isSynthetic()) {
				methodList.add(m);
			}
		}
		return methodList;
	}

Replace Generic With Diamond HashSet<Method> with HashSet<> in method private getPotentiallyOverridingMethods(c Class) : Set<Method> from class com.laytonsmith.PureUtilities.Common.Annotations.CheckOverrides


	/**
	 * Returns a list of overridable methods in a class. This includes
	 * non-static, non-private, non-final methods.
	 *
	 * @param c
	 * @return
	 */
	private static List<Method> getOverridableMethods(Class c) {
		List<Method> methodList = new ArrayList<>();
		for (Method m : c.getDeclaredMethods()) {
			if ((m.getModifiers() & Modifier.PRIVATE) == 0
					&& (m.getModifiers() & Modifier.STATIC) == 0
					&& (m.getModifiers() & Modifier.FINAL) == 0
					&& !m.isSynthetic()) {
				methodList.add(m);
			}
		}
		return methodList;
	}

	/**
	 * Returns a list of overridable methods in a class. This includes
	 * non-static, non-private, non-final methods.
	 *
	 * @param c
	 * @return
	 */
	private static List<Method> getOverridableMethods(Class c) {
		List<Method> methodList = new ArrayList<Method>();
		for (Method m : c.getDeclaredMethods()) {
			if ((m.getModifiers() & Modifier.PRIVATE) == 0
					&& (m.getModifiers() & Modifier.STATIC) == 0
					&& (m.getModifiers() & Modifier.FINAL) == 0
					&& !m.isSynthetic()) {
				methodList.add(m);
			}
		}
		return methodList;
	}

Replace Generic With Diamond ArrayList<Method> with ArrayList<> in method private getOverridableMethods(c Class) : List<Method> from class com.laytonsmith.PureUtilities.Common.Annotations.CheckOverrides


	@Override
	protected void clearKey0(DaemonManager dm, String[] key) throws ReadOnlyException, DataSourceException, IOException {
		if(hasKey(key)){
			try{
				connect();
				try (PreparedStatement statement = getConnection().prepareStatement("DELETE FROM `" + getEscapedTable() + "`"
						+ " WHERE `" + KEY_HASH_COLUMN + "`=UNHEX(MD5(?))")) {
					String joinedKey = StringUtils.Join(key, ".");
					statement.setString(1, joinedKey);
					statement.executeUpdate();
				}
				updateLastConnected();
			} catch(Exception e){
				throw new DataSourceException(e.getMessage(), e);
			}
		}
	}

	@Override
	protected void clearKey0(DaemonManager dm, String[] key) throws ReadOnlyException, DataSourceException, IOException {
		if(hasKey(key)){
			try{
				connect();
				PreparedStatement statement = getConnection().prepareStatement("DELETE FROM `" + getEscapedTable() + "`"
						+ " WHERE `" + KEY_HASH_COLUMN + "`=UNHEX(MD5(?))");
				String joinedKey = StringUtils.Join(key, ".");
				statement.setString(1, joinedKey);
				statement.executeUpdate();
				updateLastConnected();
			} catch(Exception e){
				throw new DataSourceException(e.getMessage(), e);
			}
		}
	}

Try With Resources try(PreparedStatement statement=getConnection().prepareStatement("DELETE FROM `" + getEscapedTable() + "`" + " WHERE `" + KEY_HASH_COLUMN + "`=UNHEX(MD5(?))")) in method protected clearKey0(dm DaemonManager, key String[]) : void from class com.laytonsmith.persistence.MySQLDataSource


	@Override
	protected void clearKey0(DaemonManager dm, String[] key) throws ReadOnlyException, DataSourceException, IOException {
		if(hasKey(key)){
			try{
				connect();
				try (PreparedStatement statement = connection.prepareStatement("DELETE FROM `" + getEscapedTable() + "` WHERE `" + KEY_COLUMN + "`=?")) {
					statement.setString(1, StringUtils.Join(key, "."));
					statement.executeUpdate();
				}
				lastConnected = System.currentTimeMillis();
			} catch(Exception e){
				throw new DataSourceException(e.getMessage(), e);
			}
		}
	}

	@Override
	protected void clearKey0(DaemonManager dm, String[] key) throws ReadOnlyException, DataSourceException, IOException {
		if(hasKey(key)){
			try{
				connect();
				PreparedStatement statement = connection.prepareStatement("DELETE FROM `" + getEscapedTable() + "` WHERE `" + KEY_COLUMN + "`=?");
				statement.setString(1, StringUtils.Join(key, "."));
				statement.executeUpdate();
				lastConnected = System.currentTimeMillis();
			} catch(Exception e){
				throw new DataSourceException(e.getMessage(), e);
			}
		}
	}

Try With Resources try(PreparedStatement statement=connection.prepareStatement("DELETE FROM `" + getEscapedTable() + "` WHERE `" + KEY_COLUMN + "`=?")) in method protected clearKey0(dm DaemonManager, key String[]) : void from class com.laytonsmith.persistence.SQLDataSource


	@Override
	@SuppressWarnings("SleepWhileInLoop")
	protected void clearKey0(DaemonManager dm, String[] key) throws ReadOnlyException, DataSourceException, IOException {
		try{
			connect();
			while(true){
				try {
					try (PreparedStatement statement = getConnection().prepareStatement("DELETE FROM `" + getEscapedTable()
							+ "` WHERE `" + getKeyColumn() + "`=?")) {
						statement.setString(1, StringUtils.Join(key, "."));
						statement.executeUpdate();
						updateLastConnected();
					}
				} catch(SQLException ex){
					if(ex.getMessage().startsWith("[SQLITE_BUSY]")
							// This one only happens with SETs
							|| ex.getMessage().equals("cannot commit transaction - SQL statements in progress")){
						try {
							Thread.sleep(getRandomSleepTime());
						} catch (InterruptedException ex1) {
							//
						}
					} else {
						throw ex;
					}
				}
			}
		} catch(IOException | SQLException e){
			throw new DataSourceException(e.getMessage(), e);
		} finally {
			disconnect();
		}
	}

	@Override
	@SuppressWarnings("SleepWhileInLoop")
	protected void clearKey0(DaemonManager dm, String[] key) throws ReadOnlyException, DataSourceException, IOException {
		if(hasKey(key)){
			try{
				connect();
				while(true){
					try {
						PreparedStatement statement = getConnection().prepareStatement("DELETE FROM `" + getEscapedTable()
								+ "` WHERE `" + getKeyColumn() + "`=?");
						statement.setString(1, StringUtils.Join(key, "."));
						statement.executeUpdate();
						updateLastConnected();
					} catch(SQLException ex){
						if(ex.getMessage().startsWith("[SQLITE_BUSY]")
								// This one only happens with SETs
								|| ex.getMessage().equals("cannot commit transaction - SQL statements in progress")){
							try {
								Thread.sleep(getRandomSleepTime());
							} catch (InterruptedException ex1) {
								//
							}
						} else {
							throw ex;
						}
					}
				}
			} catch(IOException | SQLException e){
				throw new DataSourceException(e.getMessage(), e);
			}
		}
	}

Try With Resources try(PreparedStatement statement=getConnection().prepareStatement("DELETE FROM `" + getEscapedTable() + "` WHERE `" + getKeyColumn() + "`=?")) in method protected clearKey0(dm DaemonManager, key String[]) : void from class com.laytonsmith.persistence.SQLiteDataSource


        private void setValue(List<String> val) {
            arrayVal = new ArrayList<>(val);
        }

        private void setValue(List<String> val) {
            arrayVal = new ArrayList<String>(val);
        }

Replace Generic With Diamond ArrayList<String> with ArrayList<> in method private setValue(val List<String>) : void from class com.laytonsmith.PureUtilities.ArgumentParser.Argument


	private void build(Object node, GenericTreeNode<Pair<String, String>> treeNode) {
		if (node instanceof Map) {
			//We need to iterate through all the keys, creating children as we go
			for (String key : ((Map<String, Object>) node).keySet()) {
				if (key.equals("_")) {
					//Special case, this is a reserved key
					build(((Map<String, Object>) node).get(key), treeNode);
				} else {
					GenericTreeNode<Pair<String, String>> newNode =
							new GenericTreeNode<>(new Pair<String, String>(key, null));
					treeNode.addChild(newNode);
					build(((Map<String, Object>) node).get(key), newNode);
				}
			}
		} else {
			//This is the node we want to put the data in
			treeNode.data.setValue(node==null?null:node.toString());
		}
	}

	private void build(Object node, GenericTreeNode<Pair<String, String>> treeNode) {
		if (node instanceof Map) {
			//We need to iterate through all the keys, creating children as we go
			for (String key : ((Map<String, Object>) node).keySet()) {
				if (key.equals("_")) {
					//Special case, this is a reserved key
					build(((Map<String, Object>) node).get(key), treeNode);
				} else {
					GenericTreeNode<Pair<String, String>> newNode =
							new GenericTreeNode<Pair<String, String>>(new Pair<String, String>(key, null));
					treeNode.addChild(newNode);
					build(((Map<String, Object>) node).get(key), newNode);
				}
			}
		} else {
			//This is the node we want to put the data in
			treeNode.data.setValue(node==null?null:node.toString());
		}
	}

Replace Generic With Diamond GenericTreeNode<Pair<String,String>> with GenericTreeNode<> in method private build(node Object, treeNode GenericTreeNode<Pair<String,String>>) : void from class com.laytonsmith.persistence.DataSourceModel


	public Map<String, Object> toMap() {
		Map<String, Object> map = new HashMap<>();
		for (GenericTreeNode<Pair<String, String>> child : tree.getChildren()) {
			decompose(map, child);
		}
		return map;
	}

	public Map<String, Object> toMap() {
		Map<String, Object> map = new HashMap<String, Object>();
		for (GenericTreeNode<Pair<String, String>> child : tree.getChildren()) {
			decompose(map, child);
		}
		return map;
	}

Replace Generic With Diamond HashMap<String,Object> with HashMap<> in method public toMap() : Map<String,Object> from class com.laytonsmith.persistence.DataSourceModel


	public List<Pair<String[], String>> toList() {
		List<Pair<String[], String>> list = new ArrayList<>();
		//TODO
		return list;
	}

	public List<Pair<String[], String>> toList() {
		List<Pair<String[], String>> list = new ArrayList<Pair<String[], String>>();
		//TODO
		return list;
	}

Replace Generic With Diamond ArrayList<Pair<String[],String>> with ArrayList<> in method public toList() : List<Pair<String[],String>> from class com.laytonsmith.persistence.DataSourceModel


	private void decompose(Map<String, Object> node, GenericTreeNode<Pair<String, String>> treeNode) {
		if (treeNode.hasChildren()) {
			//If it's not a leaf node, we need to add a new child to the map.
			//However, if the data isn't null, we need to add the data now as a _ key
			Map<String, Object> map = new HashMap<>();
			if (treeNode.getData().getValue() != null) {
				map.put("_", treeNode.getData().getValue());
			}
			node.put(treeNode.getData().getKey(), map);
			for (GenericTreeNode<Pair<String, String>> child : treeNode.getChildren()) {
				decompose(map, child);
			}
		} else {
			//It's a leaf node, so we just put the data in the map and call it a day
			node.put(treeNode.getData().getKey(), treeNode.getData().getValue());
		}
	}

	private void decompose(Map<String, Object> node, GenericTreeNode<Pair<String, String>> treeNode) {
		if (treeNode.hasChildren()) {
			//If it's not a leaf node, we need to add a new child to the map.
			//However, if the data isn't null, we need to add the data now as a _ key
			Map<String, Object> map = new HashMap<String, Object>();
			if (treeNode.getData().getValue() != null) {
				map.put("_", treeNode.getData().getValue());
			}
			node.put(treeNode.getData().getKey(), map);
			for (GenericTreeNode<Pair<String, String>> child : treeNode.getChildren()) {
				decompose(map, child);
			}
		} else {
			//It's a leaf node, so we just put the data in the map and call it a day
			node.put(treeNode.getData().getKey(), treeNode.getData().getValue());
		}
	}

Replace Generic With Diamond HashMap<String,Object> with HashMap<> in method private decompose(node Map<String,Object>, treeNode GenericTreeNode<Pair<String,String>>) : void from class com.laytonsmith.persistence.DataSourceModel


	public String get(String[] key) {
		return getValue(new ArrayList<>(Arrays.asList(key)), tree);
	}

	public String get(String[] key) {
		return getValue(new ArrayList<String>(Arrays.asList(key)), tree);
	}

Replace Generic With Diamond ArrayList<String> with ArrayList<> in method public get(key String[]) : String from class com.laytonsmith.persistence.DataSourceModel


	public void set(String[] key, String value) {
		setValue(new ArrayList<>(Arrays.asList(key)), tree, value);
	}

	public void set(String[] key, String value) {
		setValue(new ArrayList<String>(Arrays.asList(key)), tree, value);
	}

Replace Generic With Diamond ArrayList<String> with ArrayList<> in method public set(key String[], value String) : void from class com.laytonsmith.persistence.DataSourceModel


	private void setValue(List<String> keys, GenericTreeNode<Pair<String, String>> treeNode, String value) {
		if (keys.isEmpty()) {
			treeNode.getData().setValue(value);
		} else {
			GenericTreeNode<Pair<String, String>> found = null;
			String key = keys.get(0);
			keys.remove(0);
			for (GenericTreeNode<Pair<String, String>> child : treeNode.getChildren()) {
				if (child.getData().getKey().equals(key)) {
					found = child;
					break;
				}
			}
			if (found == null) {
				found = new GenericTreeNode<>(new Pair<String, String>(key, null));
				treeNode.addChild(found);
			}
			if (value == null) {
				if (keys.isEmpty()) {
					//We need to remove this node.
					//TODO: This fails to remove the parent
					for (int i = 0; i < treeNode.getNumberOfChildren(); i++) {
						GenericTreeNode<Pair<String, String>> node = treeNode.getChildAt(i);
						if (node.getData().getKey().equals(key)) {
							treeNode.removeChildAt(i);
							break;
						}
					}
					return;
				}
			}
			setValue(keys, found, value);
		}
	}

	private void setValue(List<String> keys, GenericTreeNode<Pair<String, String>> treeNode, String value) {
		if (keys.isEmpty()) {
			treeNode.getData().setValue(value);
		} else {
			GenericTreeNode<Pair<String, String>> found = null;
			String key = keys.get(0);
			keys.remove(0);
			for (GenericTreeNode<Pair<String, String>> child : treeNode.getChildren()) {
				if (child.getData().getKey().equals(key)) {
					found = child;
					break;
				}
			}
			if (found == null) {
				found = new GenericTreeNode<Pair<String, String>>(new Pair<String, String>(key, null));
				treeNode.addChild(found);
			}
			if (value == null) {
				if (keys.isEmpty()) {
					//We need to remove this node.
					//TODO: This fails to remove the parent
					for (int i = 0; i < treeNode.getNumberOfChildren(); i++) {
						GenericTreeNode<Pair<String, String>> node = treeNode.getChildAt(i);
						if (node.getData().getKey().equals(key)) {
							treeNode.removeChildAt(i);
							break;
						}
					}
					return;
				}
			}
			setValue(keys, found, value);
		}
	}

Replace Generic With Diamond GenericTreeNode<Pair<String,String>> with GenericTreeNode<> in method private setValue(keys List<String>, treeNode GenericTreeNode<Pair<String,String>>, value String) : void from class com.laytonsmith.persistence.DataSourceModel


	public Set<String[]> keySet() {
		Set<String[]> keys = new HashSet<>();
		for (GenericTreeNode child : tree.getChildren()) {
			traverse(child, new ArrayList<String>(), keys);
		}
		return keys;
	}

	public Set<String[]> keySet() {
		Set<String[]> keys = new HashSet<String[]>();
		for (GenericTreeNode child : tree.getChildren()) {
			traverse(child, new ArrayList<String>(), keys);
		}
		return keys;
	}

Replace Generic With Diamond HashSet<String[]> with HashSet<> in method public keySet() : Set<String[]> from class com.laytonsmith.persistence.DataSourceModel


        public static BukkitMCPlayerChatEvent _instantiate(MCPlayer player, String message, String format){
			AsyncPlayerChatEvent apce = new AsyncPlayerChatEvent(false, ((BukkitMCPlayer)player)._Player(), message,
                    new HashSet<>(Arrays.asList(Bukkit.getServer().getOnlinePlayers())));
			apce.setFormat(format);
            return new BukkitMCPlayerChatEvent(apce);
        }

        public static BukkitMCPlayerChatEvent _instantiate(MCPlayer player, String message, String format){
			AsyncPlayerChatEvent apce = new AsyncPlayerChatEvent(false, ((BukkitMCPlayer)player)._Player(), message,
                    new HashSet<Player>(Arrays.asList(Bukkit.getServer().getOnlinePlayers())));
			apce.setFormat(format);
            return new BukkitMCPlayerChatEvent(apce);
        }

Replace Generic With Diamond AsyncPlayerChatEvent with AsyncPlayerChatEvent in method public _instantiate(player MCPlayer, message String, format String) : BukkitMCPlayerChatEvent from class com.laytonsmith.abstraction.bukkit.events.BukkitPlayerEvents.BukkitMCPlayerChatEvent


		@Override
        public List<MCPlayer> getRecipients() {
            List<MCPlayer> players = new ArrayList<>();
            for(Player p : pce.getRecipients()){
                players.add(new BukkitMCPlayer(p));
            }
            return players;
        }

		@Override
        public List<MCPlayer> getRecipients() {
            List<MCPlayer> players = new ArrayList<MCPlayer>();
            for(Player p : pce.getRecipients()){
                players.add(new BukkitMCPlayer(p));
            }
            return players;
        }

Replace Generic With Diamond ArrayList<MCPlayer> with ArrayList<> in method public getRecipients() : List<MCPlayer> from class com.laytonsmith.abstraction.bukkit.events.BukkitPlayerEvents.BukkitMCPlayerChatEvent


	/**
	 * Process the given location for any jars. If the location is a jar, add it
	 * directly. If the location is a directory, look for jars in it.
	 *
	 * @param location file or directory
	 * @return
	 */
	private static List<File> getFiles(File location) {
		List<File> toProcess = new ArrayList<>();

		if (location.isDirectory()) {
			for (File f : location.listFiles()) {
				if (f.getName().endsWith(".jar")) {
					try {
						// Add the trimmed absolute path.
						toProcess.add(f.getCanonicalFile());
					} catch (IOException ex) {
						Logger.getLogger(ExtensionManager.class.getName()).log(
								Level.SEVERE, "Could not get exact path for "
								+ f.getAbsolutePath(), ex);
					}
				}
			}
		} else if (location.getName().endsWith(".jar")) {
			try {
				// Add the trimmed absolute path.
				toProcess.add(location.getCanonicalFile());
			} catch (IOException ex) {
				Logger.getLogger(ExtensionManager.class.getName()).log(
						Level.SEVERE, "Could not get exact path for "
						+ location.getAbsolutePath(), ex);
			}
		}

		return toProcess;
	}

	/**
	 * Process the given location for any jars. If the location is a jar, add it
	 * directly. If the location is a directory, look for jars in it.
	 *
	 * @param location file or directory
	 * @return
	 */
	private static List<File> getFiles(File location) {
		List<File> toProcess = new ArrayList<File>();

		if (location.isDirectory()) {
			for (File f : location.listFiles()) {
				if (f.getName().endsWith(".jar")) {
					try {
						// Add the trimmed absolute path.
						toProcess.add(f.getCanonicalFile());
					} catch (IOException ex) {
						Logger.getLogger(ExtensionManager.class.getName()).log(
								Level.SEVERE, "Could not get exact path for "
								+ f.getAbsolutePath(), ex);
					}
				}
			}
		} else if (location.getName().endsWith(".jar")) {
			try {
				// Add the trimmed absolute path.
				toProcess.add(location.getCanonicalFile());
			} catch (IOException ex) {
				Logger.getLogger(ExtensionManager.class.getName()).log(
						Level.SEVERE, "Could not get exact path for "
						+ location.getAbsolutePath(), ex);
			}
		}

		return toProcess;
	}

Replace Generic With Diamond ArrayList<File> with ArrayList<> in method private getFiles(location File) : List<File> from class com.laytonsmith.core.extensions.ExtensionManager


    public TagCommand() {
        super("tag",
                new HashSet<>(),
                CommandPermission.discord(Permission.MANAGE_CHANNEL),
                Stream.of(new TagListCommand(), new TagCreateCommand(), new TagDeleteCommand()).collect(Collectors.toSet()));
    }

    public TagCommand() {
        super("tag",
                new HashSet<String>(),
                CommandPermission.discord(Permission.MANAGE_CHANNEL),
                Stream.of(new TagListCommand(), new TagCreateCommand(), new TagDeleteCommand()).collect(Collectors.toSet()));
    }

Replace Generic With Diamond HashSet<String> with HashSet<> in method public TagCommand() from class com.ibdiscord.command.commands.tag.TagCommand


    @Override
    public Set<String> smembers(String key) {
        Set<String> members = new HashSet<>();
        try {
            members.addAll(sync.smembers(key));
        } catch(RedisException re) {
            re.printStackTrace();
        }
        return members;
    }

    @Override
    public Set<String> smembers(String key) {
        Set<String> members = new HashSet<String>();
        try {
            members.addAll(sync.smembers(key));
        } catch(RedisException re) {
            re.printStackTrace();
        }
        return members;
    }

Replace Generic With Diamond HashSet<String> with HashSet<> in method public smembers(key String) : Set<String> from class com.ibdiscord.data.db.DProvider