@Override
	public byte[] pingGmcp(final Session session, final Map<String,Long> reporteds, final Map<String,Double> supportables)
	{
		try
		{
			final Long nextMedReport=reporteds.get("system.nextMedReport");
			final Long nextLongReport=reporteds.get("system.nextLongReport");
			final Long nextTruePingReport=reporteds.get("system.nextTruePing");
			final long now=System.currentTimeMillis();
			final boolean charSupported=supportables.containsKey("char");
			final ByteArrayOutputStream bout=new ByteArrayOutputStream();
			final MOB mob=session.mob();
			byte[] buf;
			if(charSupported||supportables.containsKey("char.vitals"))
			{
				buf=possiblePingGmcp(session, reporteds, supportables, "char.vitals");
				if(buf!=null)
					bout.write(buf);
			}
			if((nextTruePingReport==null)||(now>nextTruePingReport.longValue()))
			{
				final long tickMillis=CharState.REAL_TICK_ADJUST_FACTOR*CMProps.getTickMillis();
				reporteds.put("system.nextTruePing", new Long((nextTruePingReport==null)?(now+tickMillis):(nextTruePingReport.longValue()+tickMillis)));
				if(supportables.containsKey("comm.tick")||supportables.containsKey("comm"))
				{
					if(CMSecurity.isDebugging(DbgFlag.TELNET))
						Log.debugOut("GMCP Sent: comm.tick { }");
					bout.write(Session.TELNETBYTES_GMCP_HEAD);
					bout.write("comm.tick { }".getBytes());
					bout.write(Session.TELNETBYTES_END_SB);
				}
			}
			if((nextMedReport==null)||(now>nextMedReport.longValue()))
			{
				reporteds.put("system.nextMedReport", new Long(now+3999));
				if(charSupported||supportables.containsKey("char.status"))
				{
					buf=possiblePingGmcp(session, reporteds, supportables, "char.status");
					if(buf!=null)
						bout.write(buf);
				}
				if((mob!=null)&&((mob.amFollowing()!=null)||(mob.numFollowers()>0)))
				{
					if(supportables.containsKey("group"))
					{
						buf=possiblePingGmcp(session, reporteds, supportables, "group");
						if(buf!=null)
							bout.write(buf);
					}
				}
			}
			if((nextLongReport==null)||(now>nextLongReport.longValue()))
			{
				reporteds.put("system.nextLongReport", new Long(now+15996));
				if(charSupported||supportables.containsKey("char.worth"))
				{
					buf=possiblePingGmcp(session, reporteds, supportables, "char.worth");
					if(buf!=null)
						bout.write(buf);
				}
				if(charSupported||supportables.containsKey("char.maxstats"))
				{
					buf=possiblePingGmcp(session, reporteds, supportables, "char.maxstats");
					if(buf!=null)
						bout.write(buf);
				}
				if(charSupported||supportables.containsKey("char.base"))
				{
					buf=possiblePingGmcp(session, reporteds, supportables, "char.base");
					if(buf!=null)
						bout.write(buf);
				}
				if(charSupported||supportables.containsKey("char.statusvars"))
				{
					buf=possiblePingGmcp(session, reporteds, supportables, "char.statusvars");
					if(buf!=null)
						bout.write(buf);
				}
			}
			final byte[] roomStuff = this.invokeRoomChangeGmcp(session, reporteds, supportables);
			if(roomStuff != null)
				bout.write(roomStuff);
			return (bout.size()==0) ? null: bout.toByteArray();
		}
		catch(final java.io.IOException ioe)
		{
			if(CMSecurity.isDebugging(DbgFlag.TELNET))
				Log.errOut(ioe);
		}
		catch(final Throwable t)
		{
			Log.errOut(t);
		}
		return null;
	}