Forgot to update grammar files too

Forgot to update grammar files too

--- DiceRollerCs/Grammar/DiceGrammarParser.cs
+++ DiceRollerCs/Grammar/DiceGrammarParser.cs
@@ -1320,6 +1320,18 @@
 		}
 		public ITerminalNode T_D() { return GetToken(DiceGrammarParser.T_D, 0); }
 		public ITerminalNode T_FUDGE() { return GetToken(DiceGrammarParser.T_FUDGE, 0); }
+		public Basic_extrasContext[] basic_extras() {
+			return GetRuleContexts<Basic_extrasContext>();
+		}
+		public Basic_extrasContext basic_extras(int i) {
+			return GetRuleContext<Basic_extrasContext>(i);
+		}
+		public Basic_functionContext[] basic_function() {
+			return GetRuleContexts<Basic_functionContext>();
+		}
+		public Basic_functionContext basic_function(int i) {
+			return GetRuleContext<Basic_functionContext>(i);
+		}
 		public BasicFudgeContext(Basic_rollContext context) { CopyFrom(context); }
 		public override void EnterRule(IParseTreeListener listener) {
 			IDiceGrammarListener typedListener = listener as IDiceGrammarListener;
@@ -1337,9 +1349,9 @@
 		EnterRule(_localctx, 26, RULE_basic_roll);
 		try {
 			int _alt;
-			State = 179;
+			State = 191;
 			ErrorHandler.Sync(this);
-			switch ( Interpreter.AdaptivePredict(TokenStream,18,Context) ) {
+			switch ( Interpreter.AdaptivePredict(TokenStream,20,Context) ) {
 			case 1:
 				_localctx = new BasicBasicContext(_localctx);
 				EnterOuterAlt(_localctx, 1);
@@ -1395,6 +1407,36 @@
 					}
 					break;
 				}
+				State = 182;
+				ErrorHandler.Sync(this);
+				_alt = Interpreter.AdaptivePredict(TokenStream,18,Context);
+				while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) {
+					if ( _alt==1 ) {
+						{
+						{
+						State = 179; basic_extras();
+						}
+						}
+					}
+					State = 184;
+					ErrorHandler.Sync(this);
+					_alt = Interpreter.AdaptivePredict(TokenStream,18,Context);
+				}
+				State = 188;
+				ErrorHandler.Sync(this);
+				_alt = Interpreter.AdaptivePredict(TokenStream,19,Context);
+				while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) {
+					if ( _alt==1 ) {
+						{
+						{
+						State = 185; basic_function();
+						}
+						}
+					}
+					State = 190;
+					ErrorHandler.Sync(this);
+					_alt = Interpreter.AdaptivePredict(TokenStream,19,Context);
+				}
 				}
 				break;
 			}
@@ -1512,7 +1554,7 @@
 		Basic_extrasContext _localctx = new Basic_extrasContext(Context, State);
 		EnterRule(_localctx, 28, RULE_basic_extras);
 		try {
-			State = 187;
+			State = 199;
 			ErrorHandler.Sync(this);
 			switch (TokenStream.LA(1)) {
 			case T_REROLL:
@@ -1520,7 +1562,7 @@
 				_localctx = new BasicRerollContext(_localctx);
 				EnterOuterAlt(_localctx, 1);
 				{
-				State = 181; reroll_expr();
+				State = 193; reroll_expr();
 				}
 				break;
 			case T_EXPLODE:
@@ -1529,7 +1571,7 @@
 				_localctx = new BasicExplodeContext(_localctx);
 				EnterOuterAlt(_localctx, 2);
 				{
-				State = 182; explode_expr();
+				State = 194; explode_expr();
 				}
 				break;
 			case T_KEEP_HIGH:
@@ -1541,7 +1583,7 @@
 				_localctx = new BasicKeepContext(_localctx);
 				EnterOuterAlt(_localctx, 3);
 				{
-				State = 183; keep_expr();
+				State = 195; keep_expr();
 				}
 				break;
 			case T_EQUALS:
@@ -1553,7 +1595,7 @@
 				_localctx = new BasicSuccessContext(_localctx);
 				EnterOuterAlt(_localctx, 4);
 				{
-				State = 184; success_expr();
+				State = 196; success_expr();
 				}
 				break;
 			case T_SORT_ASC:
@@ -1561,14 +1603,14 @@
 				_localctx = new BasicSortContext(_localctx);
 				EnterOuterAlt(_localctx, 5);
 				{
-				State = 185; sort_expr();
+				State = 197; sort_expr();
 				}
 				break;
 			case T_CRIT:
 				_localctx = new BasicCritContext(_localctx);
 				EnterOuterAlt(_localctx, 6);
 				{
-				State = 186; crit_expr();
+				State = 198; crit_expr();
 				}
 				break;
 			default:
@@ -1688,53 +1730,53 @@
 		Keep_exprContext _localctx = new Keep_exprContext(Context, State);
 		EnterRule(_localctx, 30, RULE_keep_expr);
 		try {
-			State = 199;
+			State = 211;
 			ErrorHandler.Sync(this);
 			switch (TokenStream.LA(1)) {
 			case T_KEEP_HIGH:
 				_localctx = new KeepHighContext(_localctx);
 				EnterOuterAlt(_localctx, 1);
 				{
-				State = 189; Match(T_KEEP_HIGH);
-				State = 190; number();
+				State = 201; Match(T_KEEP_HIGH);
+				State = 202; number();
 				}
 				break;
 			case T_KEEP_LOW:
 				_localctx = new KeepLowContext(_localctx);
 				EnterOuterAlt(_localctx, 2);
 				{
-				State = 191; Match(T_KEEP_LOW);
-				State = 192; number();
+				State = 203; Match(T_KEEP_LOW);
+				State = 204; number();
 				}
 				break;
 			case T_DROP_HIGH:
 				_localctx = new DropHighContext(_localctx);
 				EnterOuterAlt(_localctx, 3);
 				{
-				State = 193; Match(T_DROP_HIGH);
-				State = 194; number();
+				State = 205; Match(T_DROP_HIGH);
+				State = 206; number();
 				}
 				break;
 			case T_DROP_LOW:
 				_localctx = new DropLowContext(_localctx);
 				EnterOuterAlt(_localctx, 4);
 				{
-				State = 195; Match(T_DROP_LOW);
-				State = 196; number();
+				State = 207; Match(T_DROP_LOW);
+				State = 208; number();
 				}
 				break;
 			case T_ADVANTAGE:
 				_localctx = new AdvantageContext(_localctx);
 				EnterOuterAlt(_localctx, 5);
 				{
-				State = 197; Match(T_ADVANTAGE);
+				State = 209; Match(T_ADVANTAGE);
 				}
 				break;
 			case T_DISADVANTAGE:
 				_localctx = new DisadvantageContext(_localctx);
 				EnterOuterAlt(_localctx, 6);
 				{
-				State = 198; Match(T_DISADVANTAGE);
+				State = 210; Match(T_DISADVANTAGE);
 				}
 				break;
 			default:
@@ -1800,23 +1842,23 @@
 		Reroll_exprContext _localctx = new Reroll_exprContext(Context, State);
 		EnterRule(_localctx, 32, RULE_reroll_expr);
 		try {
-			State = 205;
+			State = 217;
 			ErrorHandler.Sync(this);
 			switch (TokenStream.LA(1)) {
 			case T_REROLL:
 				_localctx = new RerollRerollContext(_localctx);
 				EnterOuterAlt(_localctx, 1);
 				{
-				State = 201; Match(T_REROLL);
-				State = 202; compare_expr();
+				State = 213; Match(T_REROLL);
+				State = 214; compare_expr();
 				}
 				break;
 			case T_REROLL_ONCE:
 				_localctx = new RerollOnceContext(_localctx);
 				EnterOuterAlt(_localctx, 2);
 				{
-				State = 203; Match(T_REROLL_ONCE);
-				State = 204; compare_expr();
+				State = 215; Match(T_REROLL_ONCE);
+				State = 216; compare_expr();
 				}
 				break;
 			default:
@@ -1897,52 +1939,52 @@
 		Explode_exprContext _localctx = new Explode_exprContext(Context, State);
 		EnterRule(_localctx, 34, RULE_explode_expr);
 		try {
-			State = 219;
+			State = 231;
 			ErrorHandler.Sync(this);
 			switch (TokenStream.LA(1)) {
 			case T_EXPLODE:
 				_localctx = new ExplodeContext(_localctx);
 				EnterOuterAlt(_localctx, 1);
 				{
-				State = 207; Match(T_EXPLODE);
-				State = 209;
-				ErrorHandler.Sync(this);
-				switch ( Interpreter.AdaptivePredict(TokenStream,22,Context) ) {
-				case 1:
-					{
-					State = 208; compare_expr();
-					}
-					break;
-				}
-				}
-				break;
-			case T_COMPOUND:
-				_localctx = new CompoundContext(_localctx);
-				EnterOuterAlt(_localctx, 2);
-				{
-				State = 211; Match(T_COMPOUND);
-				State = 213;
-				ErrorHandler.Sync(this);
-				switch ( Interpreter.AdaptivePredict(TokenStream,23,Context) ) {
-				case 1:
-					{
-					State = 212; compare_expr();
-					}
-					break;
-				}
-				}
-				break;
-			case T_PENETRATE:
-				_localctx = new PenetrateContext(_localctx);
-				EnterOuterAlt(_localctx, 3);
-				{
-				State = 215; Match(T_PENETRATE);
-				State = 217;
+				State = 219; Match(T_EXPLODE);
+				State = 221;
 				ErrorHandler.Sync(this);
 				switch ( Interpreter.AdaptivePredict(TokenStream,24,Context) ) {
 				case 1:
 					{
-					State = 216; compare_expr();
+					State = 220; compare_expr();
+					}
+					break;
+				}
+				}
+				break;
+			case T_COMPOUND:
+				_localctx = new CompoundContext(_localctx);
+				EnterOuterAlt(_localctx, 2);
+				{
+				State = 223; Match(T_COMPOUND);
+				State = 225;
+				ErrorHandler.Sync(this);
+				switch ( Interpreter.AdaptivePredict(TokenStream,25,Context) ) {
+				case 1:
+					{
+					State = 224; compare_expr();
+					}
+					break;
+				}
+				}
+				break;
+			case T_PENETRATE:
+				_localctx = new PenetrateContext(_localctx);
+				EnterOuterAlt(_localctx, 3);
+				{
+				State = 227; Match(T_PENETRATE);
+				State = 229;
+				ErrorHandler.Sync(this);
+				switch ( Interpreter.AdaptivePredict(TokenStream,26,Context) ) {
+				case 1:
+					{
+					State = 228; compare_expr();
 					}
 					break;
 				}
@@ -1993,14 +2035,14 @@
 		try {
 			EnterOuterAlt(_localctx, 1);
 			{
-			State = 221; explicit_compare_expr();
-			State = 224;
+			State = 233; explicit_compare_expr();
+			State = 236;
 			ErrorHandler.Sync(this);
-			switch ( Interpreter.AdaptivePredict(TokenStream,26,Context) ) {
+			switch ( Interpreter.AdaptivePredict(TokenStream,28,Context) ) {
 			case 1:
 				{
-				State = 222; Match(T_FAIL);
-				State = 223; compare_expr();
+				State = 234; Match(T_FAIL);
+				State = 235; compare_expr();
 				}
 				break;
 			}
@@ -2063,7 +2105,7 @@
 		Compare_exprContext _localctx = new Compare_exprContext(Context, State);
 		EnterRule(_localctx, 38, RULE_compare_expr);
 		try {
-			State = 228;
+			State = 240;
 			ErrorHandler.Sync(this);
 			switch (TokenStream.LA(1)) {
 			case T_DIGIT_STRING:
@@ -2072,7 +2114,7 @@
 				_localctx = new CompImplicitContext(_localctx);
 				EnterOuterAlt(_localctx, 1);
 				{
-				State = 226; number();
+				State = 238; number();
 				}
 				break;
 			case T_EQUALS:
@@ -2084,7 +2126,7 @@
 				_localctx = new CompExplicitContext(_localctx);
 				EnterOuterAlt(_localctx, 2);
 				{
-				State = 227; explicit_compare_expr();
+				State = 239; explicit_compare_expr();
 				}
 				break;
 			default:
@@ -2210,55 +2252,55 @@
 		Explicit_compare_exprContext _localctx = new Explicit_compare_exprContext(Context, State);
 		EnterRule(_localctx, 40, RULE_explicit_compare_expr);
 		try {
-			State = 242;
+			State = 254;
 			ErrorHandler.Sync(this);
 			switch (TokenStream.LA(1)) {
 			case T_EQUALS:
 				_localctx = new EqualsContext(_localctx);
 				EnterOuterAlt(_localctx, 1);
 				{
-				State = 230; Match(T_EQUALS);
-				State = 231; number();
+				State = 242; Match(T_EQUALS);
+				State = 243; number();
 				}
 				break;
 			case T_GREATER:
 				_localctx = new GreaterContext(_localctx);
 				EnterOuterAlt(_localctx, 2);
 				{
-				State = 232; Match(T_GREATER);
-				State = 233; number();
+				State = 244; Match(T_GREATER);
+				State = 245; number();
 				}
 				break;
 			case T_LESS:
 				_localctx = new LessContext(_localctx);
 				EnterOuterAlt(_localctx, 3);
 				{
-				State = 234; Match(T_LESS);
-				State = 235; number();
+				State = 246; Match(T_LESS);
+				State = 247; number();
 				}
 				break;
 			case T_GREATER_EQUALS:
 				_localctx = new GreaterEqualsContext(_localctx);
 				EnterOuterAlt(_localctx, 4);
 				{
-				State = 236; Match(T_GREATER_EQUALS);
-				State = 237; number();
+				State = 248; Match(T_GREATER_EQUALS);
+				State = 249; number();
 				}
 				break;
 			case T_LESS_EQUALS:
 				_localctx = new LessEqualsContext(_localctx);
 				EnterOuterAlt(_localctx, 5);
 				{
-				State = 238; Match(T_LESS_EQUALS);
-				State = 239; number();
+				State = 250; Match(T_LESS_EQUALS);
+				State = 251; number();
 				}
 				break;
 			case T_NOT_EQUALS:
 				_localctx = new NotEqualsContext(_localctx);
 				EnterOuterAlt(_localctx, 6);
 				{
-				State = 240; Match(T_NOT_EQUALS);
-				State = 241; number();
+				State = 252; Match(T_NOT_EQUALS);
+				State = 253; number();
 				}
 				break;
 			default:
@@ -2318,21 +2360,21 @@
 		Sort_exprContext _localctx = new Sort_exprContext(Context, State);
 		EnterRule(_localctx, 42, RULE_sort_expr);
 		try {
-			State = 246;
+			State = 258;
 			ErrorHandler.Sync(this);
 			switch (TokenStream.LA(1)) {
 			case T_SORT_ASC:
 				_localctx = new SortAscContext(_localctx);
 				EnterOuterAlt(_localctx, 1);
 				{
-				State = 244; Match(T_SORT_ASC);
+				State = 256; Match(T_SORT_ASC);
 				}
 				break;
 			case T_SORT_DESC:
 				_localctx = new SortDescContext(_localctx);
 				EnterOuterAlt(_localctx, 2);
 				{
-				State = 245; Match(T_SORT_DESC);
+				State = 257; Match(T_SORT_DESC);
 				}
 				break;
 			default:
@@ -2381,15 +2423,15 @@
 		try {
 			EnterOuterAlt(_localctx, 1);
 			{
-			State = 248; Match(T_CRIT);
-			State = 249; compare_expr();
-			State = 252;
+			State = 260; Match(T_CRIT);
+			State = 261; compare_expr();
+			State = 264;
 			ErrorHandler.Sync(this);
-			switch ( Interpreter.AdaptivePredict(TokenStream,30,Context) ) {
+			switch ( Interpreter.AdaptivePredict(TokenStream,32,Context) ) {
 			case 1:
 				{
-				State = 250; Match(T_FAIL);
-				State = 251; compare_expr();
+				State = 262; Match(T_FAIL);
+				State = 263; compare_expr();
 				}
 				break;
 			}
@@ -2437,7 +2479,7 @@

 	private static char[] _serializedATN = {
 		'\x3', '\x608B', '\xA72A', '\x8133', '\xB9ED', '\x417C', '\x3BE7', '\x7786',
-		'\x5964', '\x3', ')', '\x101', '\x4', '\x2', '\t', '\x2', '\x4', '\x3',
+		'\x5964', '\x3', ')', '\x10D', '\x4', '\x2', '\t', '\x2', '\x4', '\x3',
 		'\t', '\x3', '\x4', '\x4', '\t', '\x4', '\x4', '\x5', '\t', '\x5', '\x4',
 		'\x6', '\t', '\x6', '\x4', '\a', '\t', '\a', '\x4', '\b', '\t', '\b',
 		'\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x4', '\v', '\t', '\v',
@@ -2472,189 +2514,200 @@
 		'\xF', '\xA5', '\n', '\xF', '\f', '\xF', '\xE', '\xF', '\xA8', '\v', '\xF',
 		'\x3', '\xF', '\a', '\xF', '\xAB', '\n', '\xF', '\f', '\xF', '\xE', '\xF',
 		'\xAE', '\v', '\xF', '\x3', '\xF', '\x3', '\xF', '\x3', '\xF', '\x3',
-		'\xF', '\x5', '\xF', '\xB4', '\n', '\xF', '\x5', '\xF', '\xB6', '\n',
-		'\xF', '\x3', '\x10', '\x3', '\x10', '\x3', '\x10', '\x3', '\x10', '\x3',
-		'\x10', '\x3', '\x10', '\x5', '\x10', '\xBE', '\n', '\x10', '\x3', '\x11',
-		'\x3', '\x11', '\x3', '\x11', '\x3', '\x11', '\x3', '\x11', '\x3', '\x11',
-		'\x3', '\x11', '\x3', '\x11', '\x3', '\x11', '\x3', '\x11', '\x5', '\x11',
-		'\xCA', '\n', '\x11', '\x3', '\x12', '\x3', '\x12', '\x3', '\x12', '\x3',
-		'\x12', '\x5', '\x12', '\xD0', '\n', '\x12', '\x3', '\x13', '\x3', '\x13',
-		'\x5', '\x13', '\xD4', '\n', '\x13', '\x3', '\x13', '\x3', '\x13', '\x5',
-		'\x13', '\xD8', '\n', '\x13', '\x3', '\x13', '\x3', '\x13', '\x5', '\x13',
-		'\xDC', '\n', '\x13', '\x5', '\x13', '\xDE', '\n', '\x13', '\x3', '\x14',
-		'\x3', '\x14', '\x3', '\x14', '\x5', '\x14', '\xE3', '\n', '\x14', '\x3',
-		'\x15', '\x3', '\x15', '\x5', '\x15', '\xE7', '\n', '\x15', '\x3', '\x16',
-		'\x3', '\x16', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16',
-		'\x3', '\x16', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16',
-		'\x3', '\x16', '\x5', '\x16', '\xF5', '\n', '\x16', '\x3', '\x17', '\x3',
-		'\x17', '\x5', '\x17', '\xF9', '\n', '\x17', '\x3', '\x18', '\x3', '\x18',
-		'\x3', '\x18', '\x3', '\x18', '\x5', '\x18', '\xFF', '\n', '\x18', '\x3',
-		'\x18', '\x2', '\x5', '\x6', '\b', '\x18', '\x19', '\x2', '\x4', '\x6',
-		'\b', '\n', '\f', '\xE', '\x10', '\x12', '\x14', '\x16', '\x18', '\x1A',
-		'\x1C', '\x1E', ' ', '\"', '$', '&', '(', '*', ',', '.', '\x2', '\x2',
-		'\x2', '\x117', '\x2', '\x30', '\x3', '\x2', '\x2', '\x2', '\x4', '\x34',
-		'\x3', '\x2', '\x2', '\x2', '\x6', '\x36', '\x3', '\x2', '\x2', '\x2',
-		'\b', '\x44', '\x3', '\x2', '\x2', '\x2', '\n', 'X', '\x3', '\x2', '\x2',
-		'\x2', '\f', '_', '\x3', '\x2', '\x2', '\x2', '\xE', 'h', '\x3', '\x2',
-		'\x2', '\x2', '\x10', 'j', '\x3', '\x2', '\x2', '\x2', '\x12', 'o', '\x3',
-		'\x2', '\x2', '\x2', '\x14', 'u', '\x3', '\x2', '\x2', '\x2', '\x16',
-		'\x8E', '\x3', '\x2', '\x2', '\x2', '\x18', '\x90', '\x3', '\x2', '\x2',
-		'\x2', '\x1A', '\x9E', '\x3', '\x2', '\x2', '\x2', '\x1C', '\xB5', '\x3',
-		'\x2', '\x2', '\x2', '\x1E', '\xBD', '\x3', '\x2', '\x2', '\x2', ' ',
-		'\xC9', '\x3', '\x2', '\x2', '\x2', '\"', '\xCF', '\x3', '\x2', '\x2',
-		'\x2', '$', '\xDD', '\x3', '\x2', '\x2', '\x2', '&', '\xDF', '\x3', '\x2',
-		'\x2', '\x2', '(', '\xE6', '\x3', '\x2', '\x2', '\x2', '*', '\xF4', '\x3',
-		'\x2', '\x2', '\x2', ',', '\xF8', '\x3', '\x2', '\x2', '\x2', '.', '\xFA',
-		'\x3', '\x2', '\x2', '\x2', '\x30', '\x31', '\x5', '\x4', '\x3', '\x2',
-		'\x31', '\x3', '\x3', '\x2', '\x2', '\x2', '\x32', '\x35', '\x5', '\x6',
-		'\x4', '\x2', '\x33', '\x35', '\x5', '\x10', '\t', '\x2', '\x34', '\x32',
-		'\x3', '\x2', '\x2', '\x2', '\x34', '\x33', '\x3', '\x2', '\x2', '\x2',
-		'\x35', '\x5', '\x3', '\x2', '\x2', '\x2', '\x36', '\x37', '\b', '\x4',
-		'\x1', '\x2', '\x37', '\x38', '\x5', '\b', '\x5', '\x2', '\x38', '\x41',
-		'\x3', '\x2', '\x2', '\x2', '\x39', ':', '\f', '\x5', '\x2', '\x2', ':',
-		';', '\a', '\'', '\x2', '\x2', ';', '@', '\x5', '\b', '\x5', '\x2', '<',
-		'=', '\f', '\x4', '\x2', '\x2', '=', '>', '\a', '(', '\x2', '\x2', '>',
-		'@', '\x5', '\b', '\x5', '\x2', '?', '\x39', '\x3', '\x2', '\x2', '\x2',
-		'?', '<', '\x3', '\x2', '\x2', '\x2', '@', '\x43', '\x3', '\x2', '\x2',
-		'\x2', '\x41', '?', '\x3', '\x2', '\x2', '\x2', '\x41', '\x42', '\x3',
-		'\x2', '\x2', '\x2', '\x42', '\a', '\x3', '\x2', '\x2', '\x2', '\x43',
-		'\x41', '\x3', '\x2', '\x2', '\x2', '\x44', '\x45', '\b', '\x5', '\x1',
-		'\x2', '\x45', '\x46', '\x5', '\n', '\x6', '\x2', '\x46', 'O', '\x3',
-		'\x2', '\x2', '\x2', 'G', 'H', '\f', '\x5', '\x2', '\x2', 'H', 'I', '\a',
-		'%', '\x2', '\x2', 'I', 'N', '\x5', '\n', '\x6', '\x2', 'J', 'K', '\f',
-		'\x4', '\x2', '\x2', 'K', 'L', '\a', '&', '\x2', '\x2', 'L', 'N', '\x5',
-		'\n', '\x6', '\x2', 'M', 'G', '\x3', '\x2', '\x2', '\x2', 'M', 'J', '\x3',
-		'\x2', '\x2', '\x2', 'N', 'Q', '\x3', '\x2', '\x2', '\x2', 'O', 'M', '\x3',
-		'\x2', '\x2', '\x2', 'O', 'P', '\x3', '\x2', '\x2', '\x2', 'P', '\t',
-		'\x3', '\x2', '\x2', '\x2', 'Q', 'O', '\x3', '\x2', '\x2', '\x2', 'R',
-		'S', '\a', '#', '\x2', '\x2', 'S', 'T', '\x5', '\x4', '\x3', '\x2', 'T',
-		'U', '\a', '$', '\x2', '\x2', 'U', 'Y', '\x3', '\x2', '\x2', '\x2', 'V',
-		'Y', '\x5', '\xE', '\b', '\x2', 'W', 'Y', '\x5', '\x16', '\f', '\x2',
-		'X', 'R', '\x3', '\x2', '\x2', '\x2', 'X', 'V', '\x3', '\x2', '\x2', '\x2',
-		'X', 'W', '\x3', '\x2', '\x2', '\x2', 'Y', '\v', '\x3', '\x2', '\x2',
-		'\x2', 'Z', '[', '\a', '#', '\x2', '\x2', '[', '\\', '\x5', '\x4', '\x3',
-		'\x2', '\\', ']', '\a', '$', '\x2', '\x2', ']', '`', '\x3', '\x2', '\x2',
-		'\x2', '^', '`', '\x5', '\xE', '\b', '\x2', '_', 'Z', '\x3', '\x2', '\x2',
-		'\x2', '_', '^', '\x3', '\x2', '\x2', '\x2', '`', '\r', '\x3', '\x2',
-		'\x2', '\x2', '\x61', '\x63', '\a', '&', '\x2', '\x2', '\x62', '\x61',
-		'\x3', '\x2', '\x2', '\x2', '\x62', '\x63', '\x3', '\x2', '\x2', '\x2',
-		'\x63', '\x64', '\x3', '\x2', '\x2', '\x2', '\x64', 'i', '\a', '\x3',
-		'\x2', '\x2', '\x65', '\x66', '\a', '\x1F', '\x2', '\x2', '\x66', 'g',
-		'\a', '\x5', '\x2', '\x2', 'g', 'i', '\a', ' ', '\x2', '\x2', 'h', '\x62',
-		'\x3', '\x2', '\x2', '\x2', 'h', '\x65', '\x3', '\x2', '\x2', '\x2', 'i',
-		'\xF', '\x3', '\x2', '\x2', '\x2', 'j', 'k', '\a', '\x4', '\x2', '\x2',
-		'k', 'l', '\a', '#', '\x2', '\x2', 'l', 'm', '\a', '\x5', '\x2', '\x2',
-		'm', 'n', '\a', '$', '\x2', '\x2', 'n', '\x11', '\x3', '\x2', '\x2', '\x2',
-		'o', 'p', '\a', '\"', '\x2', '\x2', 'p', 'q', '\a', '\x4', '\x2', '\x2',
-		'q', 'r', '\a', '#', '\x2', '\x2', 'r', 's', '\a', '\x5', '\x2', '\x2',
-		's', 't', '\a', '$', '\x2', '\x2', 't', '\x13', '\x3', '\x2', '\x2', '\x2',
-		'u', 'v', '\a', '\"', '\x2', '\x2', 'v', 'w', '\a', '\x4', '\x2', '\x2',
-		'w', 'x', '\a', '#', '\x2', '\x2', 'x', 'y', '\a', '\x5', '\x2', '\x2',
-		'y', 'z', '\a', '$', '\x2', '\x2', 'z', '\x15', '\x3', '\x2', '\x2', '\x2',
-		'{', '}', '\x5', '\f', '\a', '\x2', '|', '{', '\x3', '\x2', '\x2', '\x2',
-		'|', '}', '\x3', '\x2', '\x2', '\x2', '}', '~', '\x3', '\x2', '\x2', '\x2',
-		'~', '\x7F', '\a', '\x1D', '\x2', '\x2', '\x7F', '\x80', '\x5', '\x18',
-		'\r', '\x2', '\x80', '\x84', '\a', '\x1E', '\x2', '\x2', '\x81', '\x83',
-		'\x5', '\x1A', '\xE', '\x2', '\x82', '\x81', '\x3', '\x2', '\x2', '\x2',
-		'\x83', '\x86', '\x3', '\x2', '\x2', '\x2', '\x84', '\x82', '\x3', '\x2',
-		'\x2', '\x2', '\x84', '\x85', '\x3', '\x2', '\x2', '\x2', '\x85', '\x8A',
-		'\x3', '\x2', '\x2', '\x2', '\x86', '\x84', '\x3', '\x2', '\x2', '\x2',
-		'\x87', '\x89', '\x5', '\x12', '\n', '\x2', '\x88', '\x87', '\x3', '\x2',
-		'\x2', '\x2', '\x89', '\x8C', '\x3', '\x2', '\x2', '\x2', '\x8A', '\x88',
-		'\x3', '\x2', '\x2', '\x2', '\x8A', '\x8B', '\x3', '\x2', '\x2', '\x2',
-		'\x8B', '\x8F', '\x3', '\x2', '\x2', '\x2', '\x8C', '\x8A', '\x3', '\x2',
-		'\x2', '\x2', '\x8D', '\x8F', '\x5', '\x1C', '\xF', '\x2', '\x8E', '|',
-		'\x3', '\x2', '\x2', '\x2', '\x8E', '\x8D', '\x3', '\x2', '\x2', '\x2',
-		'\x8F', '\x17', '\x3', '\x2', '\x2', '\x2', '\x90', '\x91', '\b', '\r',
-		'\x1', '\x2', '\x91', '\x92', '\x5', '\x4', '\x3', '\x2', '\x92', '\x98',
-		'\x3', '\x2', '\x2', '\x2', '\x93', '\x94', '\f', '\x4', '\x2', '\x2',
-		'\x94', '\x95', '\a', '!', '\x2', '\x2', '\x95', '\x97', '\x5', '\x4',
-		'\x3', '\x2', '\x96', '\x93', '\x3', '\x2', '\x2', '\x2', '\x97', '\x9A',
-		'\x3', '\x2', '\x2', '\x2', '\x98', '\x96', '\x3', '\x2', '\x2', '\x2',
-		'\x98', '\x99', '\x3', '\x2', '\x2', '\x2', '\x99', '\x19', '\x3', '\x2',
-		'\x2', '\x2', '\x9A', '\x98', '\x3', '\x2', '\x2', '\x2', '\x9B', '\x9F',
-		'\x5', ' ', '\x11', '\x2', '\x9C', '\x9F', '\x5', '&', '\x14', '\x2',
-		'\x9D', '\x9F', '\x5', ',', '\x17', '\x2', '\x9E', '\x9B', '\x3', '\x2',
-		'\x2', '\x2', '\x9E', '\x9C', '\x3', '\x2', '\x2', '\x2', '\x9E', '\x9D',
-		'\x3', '\x2', '\x2', '\x2', '\x9F', '\x1B', '\x3', '\x2', '\x2', '\x2',
-		'\xA0', '\xA1', '\x5', '\f', '\a', '\x2', '\xA1', '\xA2', '\a', '\x6',
-		'\x2', '\x2', '\xA2', '\xA6', '\x5', '\f', '\a', '\x2', '\xA3', '\xA5',
-		'\x5', '\x1E', '\x10', '\x2', '\xA4', '\xA3', '\x3', '\x2', '\x2', '\x2',
-		'\xA5', '\xA8', '\x3', '\x2', '\x2', '\x2', '\xA6', '\xA4', '\x3', '\x2',
-		'\x2', '\x2', '\xA6', '\xA7', '\x3', '\x2', '\x2', '\x2', '\xA7', '\xAC',
-		'\x3', '\x2', '\x2', '\x2', '\xA8', '\xA6', '\x3', '\x2', '\x2', '\x2',
-		'\xA9', '\xAB', '\x5', '\x14', '\v', '\x2', '\xAA', '\xA9', '\x3', '\x2',
-		'\x2', '\x2', '\xAB', '\xAE', '\x3', '\x2', '\x2', '\x2', '\xAC', '\xAA',
-		'\x3', '\x2', '\x2', '\x2', '\xAC', '\xAD', '\x3', '\x2', '\x2', '\x2',
-		'\xAD', '\xB6', '\x3', '\x2', '\x2', '\x2', '\xAE', '\xAC', '\x3', '\x2',
-		'\x2', '\x2', '\xAF', '\xB0', '\x5', '\f', '\a', '\x2', '\xB0', '\xB1',
-		'\a', '\x6', '\x2', '\x2', '\xB1', '\xB3', '\a', '\a', '\x2', '\x2', '\xB2',
-		'\xB4', '\x5', '\f', '\a', '\x2', '\xB3', '\xB2', '\x3', '\x2', '\x2',
-		'\x2', '\xB3', '\xB4', '\x3', '\x2', '\x2', '\x2', '\xB4', '\xB6', '\x3',
-		'\x2', '\x2', '\x2', '\xB5', '\xA0', '\x3', '\x2', '\x2', '\x2', '\xB5',
-		'\xAF', '\x3', '\x2', '\x2', '\x2', '\xB6', '\x1D', '\x3', '\x2', '\x2',
-		'\x2', '\xB7', '\xBE', '\x5', '\"', '\x12', '\x2', '\xB8', '\xBE', '\x5',
-		'$', '\x13', '\x2', '\xB9', '\xBE', '\x5', ' ', '\x11', '\x2', '\xBA',
-		'\xBE', '\x5', '&', '\x14', '\x2', '\xBB', '\xBE', '\x5', ',', '\x17',
-		'\x2', '\xBC', '\xBE', '\x5', '.', '\x18', '\x2', '\xBD', '\xB7', '\x3',
-		'\x2', '\x2', '\x2', '\xBD', '\xB8', '\x3', '\x2', '\x2', '\x2', '\xBD',
-		'\xB9', '\x3', '\x2', '\x2', '\x2', '\xBD', '\xBA', '\x3', '\x2', '\x2',
-		'\x2', '\xBD', '\xBB', '\x3', '\x2', '\x2', '\x2', '\xBD', '\xBC', '\x3',
-		'\x2', '\x2', '\x2', '\xBE', '\x1F', '\x3', '\x2', '\x2', '\x2', '\xBF',
-		'\xC0', '\a', '\b', '\x2', '\x2', '\xC0', '\xCA', '\x5', '\xE', '\b',
-		'\x2', '\xC1', '\xC2', '\a', '\t', '\x2', '\x2', '\xC2', '\xCA', '\x5',
-		'\xE', '\b', '\x2', '\xC3', '\xC4', '\a', '\n', '\x2', '\x2', '\xC4',
-		'\xCA', '\x5', '\xE', '\b', '\x2', '\xC5', '\xC6', '\a', '\v', '\x2',
-		'\x2', '\xC6', '\xCA', '\x5', '\xE', '\b', '\x2', '\xC7', '\xCA', '\a',
-		'\f', '\x2', '\x2', '\xC8', '\xCA', '\a', '\r', '\x2', '\x2', '\xC9',
-		'\xBF', '\x3', '\x2', '\x2', '\x2', '\xC9', '\xC1', '\x3', '\x2', '\x2',
-		'\x2', '\xC9', '\xC3', '\x3', '\x2', '\x2', '\x2', '\xC9', '\xC5', '\x3',
-		'\x2', '\x2', '\x2', '\xC9', '\xC7', '\x3', '\x2', '\x2', '\x2', '\xC9',
-		'\xC8', '\x3', '\x2', '\x2', '\x2', '\xCA', '!', '\x3', '\x2', '\x2',
-		'\x2', '\xCB', '\xCC', '\a', '\xE', '\x2', '\x2', '\xCC', '\xD0', '\x5',
-		'(', '\x15', '\x2', '\xCD', '\xCE', '\a', '\xF', '\x2', '\x2', '\xCE',
-		'\xD0', '\x5', '(', '\x15', '\x2', '\xCF', '\xCB', '\x3', '\x2', '\x2',
-		'\x2', '\xCF', '\xCD', '\x3', '\x2', '\x2', '\x2', '\xD0', '#', '\x3',
-		'\x2', '\x2', '\x2', '\xD1', '\xD3', '\a', '\x10', '\x2', '\x2', '\xD2',
-		'\xD4', '\x5', '(', '\x15', '\x2', '\xD3', '\xD2', '\x3', '\x2', '\x2',
-		'\x2', '\xD3', '\xD4', '\x3', '\x2', '\x2', '\x2', '\xD4', '\xDE', '\x3',
-		'\x2', '\x2', '\x2', '\xD5', '\xD7', '\a', '\x11', '\x2', '\x2', '\xD6',
-		'\xD8', '\x5', '(', '\x15', '\x2', '\xD7', '\xD6', '\x3', '\x2', '\x2',
-		'\x2', '\xD7', '\xD8', '\x3', '\x2', '\x2', '\x2', '\xD8', '\xDE', '\x3',
-		'\x2', '\x2', '\x2', '\xD9', '\xDB', '\a', '\x12', '\x2', '\x2', '\xDA',
-		'\xDC', '\x5', '(', '\x15', '\x2', '\xDB', '\xDA', '\x3', '\x2', '\x2',
-		'\x2', '\xDB', '\xDC', '\x3', '\x2', '\x2', '\x2', '\xDC', '\xDE', '\x3',
-		'\x2', '\x2', '\x2', '\xDD', '\xD1', '\x3', '\x2', '\x2', '\x2', '\xDD',
-		'\xD5', '\x3', '\x2', '\x2', '\x2', '\xDD', '\xD9', '\x3', '\x2', '\x2',
-		'\x2', '\xDE', '%', '\x3', '\x2', '\x2', '\x2', '\xDF', '\xE2', '\x5',
-		'*', '\x16', '\x2', '\xE0', '\xE1', '\a', '\x14', '\x2', '\x2', '\xE1',
-		'\xE3', '\x5', '(', '\x15', '\x2', '\xE2', '\xE0', '\x3', '\x2', '\x2',
-		'\x2', '\xE2', '\xE3', '\x3', '\x2', '\x2', '\x2', '\xE3', '\'', '\x3',
-		'\x2', '\x2', '\x2', '\xE4', '\xE7', '\x5', '\xE', '\b', '\x2', '\xE5',
-		'\xE7', '\x5', '*', '\x16', '\x2', '\xE6', '\xE4', '\x3', '\x2', '\x2',
-		'\x2', '\xE6', '\xE5', '\x3', '\x2', '\x2', '\x2', '\xE7', ')', '\x3',
-		'\x2', '\x2', '\x2', '\xE8', '\xE9', '\a', '\x17', '\x2', '\x2', '\xE9',
-		'\xF5', '\x5', '\xE', '\b', '\x2', '\xEA', '\xEB', '\a', '\x18', '\x2',
-		'\x2', '\xEB', '\xF5', '\x5', '\xE', '\b', '\x2', '\xEC', '\xED', '\a',
-		'\x19', '\x2', '\x2', '\xED', '\xF5', '\x5', '\xE', '\b', '\x2', '\xEE',
-		'\xEF', '\a', '\x1A', '\x2', '\x2', '\xEF', '\xF5', '\x5', '\xE', '\b',
-		'\x2', '\xF0', '\xF1', '\a', '\x1B', '\x2', '\x2', '\xF1', '\xF5', '\x5',
-		'\xE', '\b', '\x2', '\xF2', '\xF3', '\a', '\x1C', '\x2', '\x2', '\xF3',
-		'\xF5', '\x5', '\xE', '\b', '\x2', '\xF4', '\xE8', '\x3', '\x2', '\x2',
-		'\x2', '\xF4', '\xEA', '\x3', '\x2', '\x2', '\x2', '\xF4', '\xEC', '\x3',
-		'\x2', '\x2', '\x2', '\xF4', '\xEE', '\x3', '\x2', '\x2', '\x2', '\xF4',
-		'\xF0', '\x3', '\x2', '\x2', '\x2', '\xF4', '\xF2', '\x3', '\x2', '\x2',
-		'\x2', '\xF5', '+', '\x3', '\x2', '\x2', '\x2', '\xF6', '\xF9', '\a',
-		'\x15', '\x2', '\x2', '\xF7', '\xF9', '\a', '\x16', '\x2', '\x2', '\xF8',
-		'\xF6', '\x3', '\x2', '\x2', '\x2', '\xF8', '\xF7', '\x3', '\x2', '\x2',
-		'\x2', '\xF9', '-', '\x3', '\x2', '\x2', '\x2', '\xFA', '\xFB', '\a',
-		'\x13', '\x2', '\x2', '\xFB', '\xFE', '\x5', '(', '\x15', '\x2', '\xFC',
-		'\xFD', '\a', '\x14', '\x2', '\x2', '\xFD', '\xFF', '\x5', '(', '\x15',
-		'\x2', '\xFE', '\xFC', '\x3', '\x2', '\x2', '\x2', '\xFE', '\xFF', '\x3',
-		'\x2', '\x2', '\x2', '\xFF', '/', '\x3', '\x2', '\x2', '\x2', '!', '\x34',
-		'?', '\x41', 'M', 'O', 'X', '_', '\x62', 'h', '|', '\x84', '\x8A', '\x8E',
-		'\x98', '\x9E', '\xA6', '\xAC', '\xB3', '\xB5', '\xBD', '\xC9', '\xCF',
-		'\xD3', '\xD7', '\xDB', '\xDD', '\xE2', '\xE6', '\xF4', '\xF8', '\xFE',
+		'\xF', '\x5', '\xF', '\xB4', '\n', '\xF', '\x3', '\xF', '\a', '\xF', '\xB7',
+		'\n', '\xF', '\f', '\xF', '\xE', '\xF', '\xBA', '\v', '\xF', '\x3', '\xF',
+		'\a', '\xF', '\xBD', '\n', '\xF', '\f', '\xF', '\xE', '\xF', '\xC0', '\v',
+		'\xF', '\x5', '\xF', '\xC2', '\n', '\xF', '\x3', '\x10', '\x3', '\x10',
+		'\x3', '\x10', '\x3', '\x10', '\x3', '\x10', '\x3', '\x10', '\x5', '\x10',
+		'\xCA', '\n', '\x10', '\x3', '\x11', '\x3', '\x11', '\x3', '\x11', '\x3',
+		'\x11', '\x3', '\x11', '\x3', '\x11', '\x3', '\x11', '\x3', '\x11', '\x3',
+		'\x11', '\x3', '\x11', '\x5', '\x11', '\xD6', '\n', '\x11', '\x3', '\x12',
+		'\x3', '\x12', '\x3', '\x12', '\x3', '\x12', '\x5', '\x12', '\xDC', '\n',
+		'\x12', '\x3', '\x13', '\x3', '\x13', '\x5', '\x13', '\xE0', '\n', '\x13',
+		'\x3', '\x13', '\x3', '\x13', '\x5', '\x13', '\xE4', '\n', '\x13', '\x3',
+		'\x13', '\x3', '\x13', '\x5', '\x13', '\xE8', '\n', '\x13', '\x5', '\x13',
+		'\xEA', '\n', '\x13', '\x3', '\x14', '\x3', '\x14', '\x3', '\x14', '\x5',
+		'\x14', '\xEF', '\n', '\x14', '\x3', '\x15', '\x3', '\x15', '\x5', '\x15',
+		'\xF3', '\n', '\x15', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16', '\x3',
+		'\x16', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16', '\x3',
+		'\x16', '\x3', '\x16', '\x3', '\x16', '\x3', '\x16', '\x5', '\x16', '\x101',
+		'\n', '\x16', '\x3', '\x17', '\x3', '\x17', '\x5', '\x17', '\x105', '\n',
+		'\x17', '\x3', '\x18', '\x3', '\x18', '\x3', '\x18', '\x3', '\x18', '\x5',
+		'\x18', '\x10B', '\n', '\x18', '\x3', '\x18', '\x2', '\x5', '\x6', '\b',
+		'\x18', '\x19', '\x2', '\x4', '\x6', '\b', '\n', '\f', '\xE', '\x10',
+		'\x12', '\x14', '\x16', '\x18', '\x1A', '\x1C', '\x1E', ' ', '\"', '$',
+		'&', '(', '*', ',', '.', '\x2', '\x2', '\x2', '\x125', '\x2', '\x30',
+		'\x3', '\x2', '\x2', '\x2', '\x4', '\x34', '\x3', '\x2', '\x2', '\x2',
+		'\x6', '\x36', '\x3', '\x2', '\x2', '\x2', '\b', '\x44', '\x3', '\x2',
+		'\x2', '\x2', '\n', 'X', '\x3', '\x2', '\x2', '\x2', '\f', '_', '\x3',
+		'\x2', '\x2', '\x2', '\xE', 'h', '\x3', '\x2', '\x2', '\x2', '\x10', 'j',
+		'\x3', '\x2', '\x2', '\x2', '\x12', 'o', '\x3', '\x2', '\x2', '\x2', '\x14',
+		'u', '\x3', '\x2', '\x2', '\x2', '\x16', '\x8E', '\x3', '\x2', '\x2',
+		'\x2', '\x18', '\x90', '\x3', '\x2', '\x2', '\x2', '\x1A', '\x9E', '\x3',
+		'\x2', '\x2', '\x2', '\x1C', '\xC1', '\x3', '\x2', '\x2', '\x2', '\x1E',
+		'\xC9', '\x3', '\x2', '\x2', '\x2', ' ', '\xD5', '\x3', '\x2', '\x2',
+		'\x2', '\"', '\xDB', '\x3', '\x2', '\x2', '\x2', '$', '\xE9', '\x3', '\x2',
+		'\x2', '\x2', '&', '\xEB', '\x3', '\x2', '\x2', '\x2', '(', '\xF2', '\x3',
+		'\x2', '\x2', '\x2', '*', '\x100', '\x3', '\x2', '\x2', '\x2', ',', '\x104',
+		'\x3', '\x2', '\x2', '\x2', '.', '\x106', '\x3', '\x2', '\x2', '\x2',
+		'\x30', '\x31', '\x5', '\x4', '\x3', '\x2', '\x31', '\x3', '\x3', '\x2',
+		'\x2', '\x2', '\x32', '\x35', '\x5', '\x6', '\x4', '\x2', '\x33', '\x35',
+		'\x5', '\x10', '\t', '\x2', '\x34', '\x32', '\x3', '\x2', '\x2', '\x2',
+		'\x34', '\x33', '\x3', '\x2', '\x2', '\x2', '\x35', '\x5', '\x3', '\x2',
+		'\x2', '\x2', '\x36', '\x37', '\b', '\x4', '\x1', '\x2', '\x37', '\x38',
+		'\x5', '\b', '\x5', '\x2', '\x38', '\x41', '\x3', '\x2', '\x2', '\x2',
+		'\x39', ':', '\f', '\x5', '\x2', '\x2', ':', ';', '\a', '\'', '\x2', '\x2',
+		';', '@', '\x5', '\b', '\x5', '\x2', '<', '=', '\f', '\x4', '\x2', '\x2',
+		'=', '>', '\a', '(', '\x2', '\x2', '>', '@', '\x5', '\b', '\x5', '\x2',
+		'?', '\x39', '\x3', '\x2', '\x2', '\x2', '?', '<', '\x3', '\x2', '\x2',
+		'\x2', '@', '\x43', '\x3', '\x2', '\x2', '\x2', '\x41', '?', '\x3', '\x2',
+		'\x2', '\x2', '\x41', '\x42', '\x3', '\x2', '\x2', '\x2', '\x42', '\a',
+		'\x3', '\x2', '\x2', '\x2', '\x43', '\x41', '\x3', '\x2', '\x2', '\x2',
+		'\x44', '\x45', '\b', '\x5', '\x1', '\x2', '\x45', '\x46', '\x5', '\n',
+		'\x6', '\x2', '\x46', 'O', '\x3', '\x2', '\x2', '\x2', 'G', 'H', '\f',
+		'\x5', '\x2', '\x2', 'H', 'I', '\a', '%', '\x2', '\x2', 'I', 'N', '\x5',
+		'\n', '\x6', '\x2', 'J', 'K', '\f', '\x4', '\x2', '\x2', 'K', 'L', '\a',
+		'&', '\x2', '\x2', 'L', 'N', '\x5', '\n', '\x6', '\x2', 'M', 'G', '\x3',
+		'\x2', '\x2', '\x2', 'M', 'J', '\x3', '\x2', '\x2', '\x2', 'N', 'Q', '\x3',
+		'\x2', '\x2', '\x2', 'O', 'M', '\x3', '\x2', '\x2', '\x2', 'O', 'P', '\x3',
+		'\x2', '\x2', '\x2', 'P', '\t', '\x3', '\x2', '\x2', '\x2', 'Q', 'O',
+		'\x3', '\x2', '\x2', '\x2', 'R', 'S', '\a', '#', '\x2', '\x2', 'S', 'T',
+		'\x5', '\x4', '\x3', '\x2', 'T', 'U', '\a', '$', '\x2', '\x2', 'U', 'Y',
+		'\x3', '\x2', '\x2', '\x2', 'V', 'Y', '\x5', '\xE', '\b', '\x2', 'W',
+		'Y', '\x5', '\x16', '\f', '\x2', 'X', 'R', '\x3', '\x2', '\x2', '\x2',
+		'X', 'V', '\x3', '\x2', '\x2', '\x2', 'X', 'W', '\x3', '\x2', '\x2', '\x2',
+		'Y', '\v', '\x3', '\x2', '\x2', '\x2', 'Z', '[', '\a', '#', '\x2', '\x2',
+		'[', '\\', '\x5', '\x4', '\x3', '\x2', '\\', ']', '\a', '$', '\x2', '\x2',
+		']', '`', '\x3', '\x2', '\x2', '\x2', '^', '`', '\x5', '\xE', '\b', '\x2',
+		'_', 'Z', '\x3', '\x2', '\x2', '\x2', '_', '^', '\x3', '\x2', '\x2', '\x2',
+		'`', '\r', '\x3', '\x2', '\x2', '\x2', '\x61', '\x63', '\a', '&', '\x2',
+		'\x2', '\x62', '\x61', '\x3', '\x2', '\x2', '\x2', '\x62', '\x63', '\x3',
+		'\x2', '\x2', '\x2', '\x63', '\x64', '\x3', '\x2', '\x2', '\x2', '\x64',
+		'i', '\a', '\x3', '\x2', '\x2', '\x65', '\x66', '\a', '\x1F', '\x2', '\x2',
+		'\x66', 'g', '\a', '\x5', '\x2', '\x2', 'g', 'i', '\a', ' ', '\x2', '\x2',
+		'h', '\x62', '\x3', '\x2', '\x2', '\x2', 'h', '\x65', '\x3', '\x2', '\x2',
+		'\x2', 'i', '\xF', '\x3', '\x2', '\x2', '\x2', 'j', 'k', '\a', '\x4',
+		'\x2', '\x2', 'k', 'l', '\a', '#', '\x2', '\x2', 'l', 'm', '\a', '\x5',
+		'\x2', '\x2', 'm', 'n', '\a', '$', '\x2', '\x2', 'n', '\x11', '\x3', '\x2',
+		'\x2', '\x2', 'o', 'p', '\a', '\"', '\x2', '\x2', 'p', 'q', '\a', '\x4',
+		'\x2', '\x2', 'q', 'r', '\a', '#', '\x2', '\x2', 'r', 's', '\a', '\x5',
+		'\x2', '\x2', 's', 't', '\a', '$', '\x2', '\x2', 't', '\x13', '\x3', '\x2',
+		'\x2', '\x2', 'u', 'v', '\a', '\"', '\x2', '\x2', 'v', 'w', '\a', '\x4',
+		'\x2', '\x2', 'w', 'x', '\a', '#', '\x2', '\x2', 'x', 'y', '\a', '\x5',
+		'\x2', '\x2', 'y', 'z', '\a', '$', '\x2', '\x2', 'z', '\x15', '\x3', '\x2',
+		'\x2', '\x2', '{', '}', '\x5', '\f', '\a', '\x2', '|', '{', '\x3', '\x2',
+		'\x2', '\x2', '|', '}', '\x3', '\x2', '\x2', '\x2', '}', '~', '\x3', '\x2',
+		'\x2', '\x2', '~', '\x7F', '\a', '\x1D', '\x2', '\x2', '\x7F', '\x80',
+		'\x5', '\x18', '\r', '\x2', '\x80', '\x84', '\a', '\x1E', '\x2', '\x2',
+		'\x81', '\x83', '\x5', '\x1A', '\xE', '\x2', '\x82', '\x81', '\x3', '\x2',
+		'\x2', '\x2', '\x83', '\x86', '\x3', '\x2', '\x2', '\x2', '\x84', '\x82',
+		'\x3', '\x2', '\x2', '\x2', '\x84', '\x85', '\x3', '\x2', '\x2', '\x2',
+		'\x85', '\x8A', '\x3', '\x2', '\x2', '\x2', '\x86', '\x84', '\x3', '\x2',
+		'\x2', '\x2', '\x87', '\x89', '\x5', '\x12', '\n', '\x2', '\x88', '\x87',
+		'\x3', '\x2', '\x2', '\x2', '\x89', '\x8C', '\x3', '\x2', '\x2', '\x2',
+		'\x8A', '\x88', '\x3', '\x2', '\x2', '\x2', '\x8A', '\x8B', '\x3', '\x2',
+		'\x2', '\x2', '\x8B', '\x8F', '\x3', '\x2', '\x2', '\x2', '\x8C', '\x8A',
+		'\x3', '\x2', '\x2', '\x2', '\x8D', '\x8F', '\x5', '\x1C', '\xF', '\x2',
+		'\x8E', '|', '\x3', '\x2', '\x2', '\x2', '\x8E', '\x8D', '\x3', '\x2',
+		'\x2', '\x2', '\x8F', '\x17', '\x3', '\x2', '\x2', '\x2', '\x90', '\x91',
+		'\b', '\r', '\x1', '\x2', '\x91', '\x92', '\x5', '\x4', '\x3', '\x2',
+		'\x92', '\x98', '\x3', '\x2', '\x2', '\x2', '\x93', '\x94', '\f', '\x4',
+		'\x2', '\x2', '\x94', '\x95', '\a', '!', '\x2', '\x2', '\x95', '\x97',
+		'\x5', '\x4', '\x3', '\x2', '\x96', '\x93', '\x3', '\x2', '\x2', '\x2',
+		'\x97', '\x9A', '\x3', '\x2', '\x2', '\x2', '\x98', '\x96', '\x3', '\x2',
+		'\x2', '\x2', '\x98', '\x99', '\x3', '\x2', '\x2', '\x2', '\x99', '\x19',
+		'\x3', '\x2', '\x2', '\x2', '\x9A', '\x98', '\x3', '\x2', '\x2', '\x2',
+		'\x9B', '\x9F', '\x5', ' ', '\x11', '\x2', '\x9C', '\x9F', '\x5', '&',
+		'\x14', '\x2', '\x9D', '\x9F', '\x5', ',', '\x17', '\x2', '\x9E', '\x9B',
+		'\x3', '\x2', '\x2', '\x2', '\x9E', '\x9C', '\x3', '\x2', '\x2', '\x2',
+		'\x9E', '\x9D', '\x3', '\x2', '\x2', '\x2', '\x9F', '\x1B', '\x3', '\x2',
+		'\x2', '\x2', '\xA0', '\xA1', '\x5', '\f', '\a', '\x2', '\xA1', '\xA2',
+		'\a', '\x6', '\x2', '\x2', '\xA2', '\xA6', '\x5', '\f', '\a', '\x2', '\xA3',
+		'\xA5', '\x5', '\x1E', '\x10', '\x2', '\xA4', '\xA3', '\x3', '\x2', '\x2',
+		'\x2', '\xA5', '\xA8', '\x3', '\x2', '\x2', '\x2', '\xA6', '\xA4', '\x3',
+		'\x2', '\x2', '\x2', '\xA6', '\xA7', '\x3', '\x2', '\x2', '\x2', '\xA7',
+		'\xAC', '\x3', '\x2', '\x2', '\x2', '\xA8', '\xA6', '\x3', '\x2', '\x2',
+		'\x2', '\xA9', '\xAB', '\x5', '\x14', '\v', '\x2', '\xAA', '\xA9', '\x3',
+		'\x2', '\x2', '\x2', '\xAB', '\xAE', '\x3', '\x2', '\x2', '\x2', '\xAC',
+		'\xAA', '\x3', '\x2', '\x2', '\x2', '\xAC', '\xAD', '\x3', '\x2', '\x2',
+		'\x2', '\xAD', '\xC2', '\x3', '\x2', '\x2', '\x2', '\xAE', '\xAC', '\x3',
+		'\x2', '\x2', '\x2', '\xAF', '\xB0', '\x5', '\f', '\a', '\x2', '\xB0',
+		'\xB1', '\a', '\x6', '\x2', '\x2', '\xB1', '\xB3', '\a', '\a', '\x2',
+		'\x2', '\xB2', '\xB4', '\x5', '\f', '\a', '\x2', '\xB3', '\xB2', '\x3',
+		'\x2', '\x2', '\x2', '\xB3', '\xB4', '\x3', '\x2', '\x2', '\x2', '\xB4',
+		'\xB8', '\x3', '\x2', '\x2', '\x2', '\xB5', '\xB7', '\x5', '\x1E', '\x10',
+		'\x2', '\xB6', '\xB5', '\x3', '\x2', '\x2', '\x2', '\xB7', '\xBA', '\x3',
+		'\x2', '\x2', '\x2', '\xB8', '\xB6', '\x3', '\x2', '\x2', '\x2', '\xB8',
+		'\xB9', '\x3', '\x2', '\x2', '\x2', '\xB9', '\xBE', '\x3', '\x2', '\x2',
+		'\x2', '\xBA', '\xB8', '\x3', '\x2', '\x2', '\x2', '\xBB', '\xBD', '\x5',
+		'\x14', '\v', '\x2', '\xBC', '\xBB', '\x3', '\x2', '\x2', '\x2', '\xBD',
+		'\xC0', '\x3', '\x2', '\x2', '\x2', '\xBE', '\xBC', '\x3', '\x2', '\x2',
+		'\x2', '\xBE', '\xBF', '\x3', '\x2', '\x2', '\x2', '\xBF', '\xC2', '\x3',
+		'\x2', '\x2', '\x2', '\xC0', '\xBE', '\x3', '\x2', '\x2', '\x2', '\xC1',
+		'\xA0', '\x3', '\x2', '\x2', '\x2', '\xC1', '\xAF', '\x3', '\x2', '\x2',
+		'\x2', '\xC2', '\x1D', '\x3', '\x2', '\x2', '\x2', '\xC3', '\xCA', '\x5',
+		'\"', '\x12', '\x2', '\xC4', '\xCA', '\x5', '$', '\x13', '\x2', '\xC5',
+		'\xCA', '\x5', ' ', '\x11', '\x2', '\xC6', '\xCA', '\x5', '&', '\x14',
+		'\x2', '\xC7', '\xCA', '\x5', ',', '\x17', '\x2', '\xC8', '\xCA', '\x5',
+		'.', '\x18', '\x2', '\xC9', '\xC3', '\x3', '\x2', '\x2', '\x2', '\xC9',
+		'\xC4', '\x3', '\x2', '\x2', '\x2', '\xC9', '\xC5', '\x3', '\x2', '\x2',
+		'\x2', '\xC9', '\xC6', '\x3', '\x2', '\x2', '\x2', '\xC9', '\xC7', '\x3',
+		'\x2', '\x2', '\x2', '\xC9', '\xC8', '\x3', '\x2', '\x2', '\x2', '\xCA',
+		'\x1F', '\x3', '\x2', '\x2', '\x2', '\xCB', '\xCC', '\a', '\b', '\x2',
+		'\x2', '\xCC', '\xD6', '\x5', '\xE', '\b', '\x2', '\xCD', '\xCE', '\a',
+		'\t', '\x2', '\x2', '\xCE', '\xD6', '\x5', '\xE', '\b', '\x2', '\xCF',
+		'\xD0', '\a', '\n', '\x2', '\x2', '\xD0', '\xD6', '\x5', '\xE', '\b',
+		'\x2', '\xD1', '\xD2', '\a', '\v', '\x2', '\x2', '\xD2', '\xD6', '\x5',
+		'\xE', '\b', '\x2', '\xD3', '\xD6', '\a', '\f', '\x2', '\x2', '\xD4',
+		'\xD6', '\a', '\r', '\x2', '\x2', '\xD5', '\xCB', '\x3', '\x2', '\x2',
+		'\x2', '\xD5', '\xCD', '\x3', '\x2', '\x2', '\x2', '\xD5', '\xCF', '\x3',
+		'\x2', '\x2', '\x2', '\xD5', '\xD1', '\x3', '\x2', '\x2', '\x2', '\xD5',
+		'\xD3', '\x3', '\x2', '\x2', '\x2', '\xD5', '\xD4', '\x3', '\x2', '\x2',
+		'\x2', '\xD6', '!', '\x3', '\x2', '\x2', '\x2', '\xD7', '\xD8', '\a',
+		'\xE', '\x2', '\x2', '\xD8', '\xDC', '\x5', '(', '\x15', '\x2', '\xD9',
+		'\xDA', '\a', '\xF', '\x2', '\x2', '\xDA', '\xDC', '\x5', '(', '\x15',
+		'\x2', '\xDB', '\xD7', '\x3', '\x2', '\x2', '\x2', '\xDB', '\xD9', '\x3',
+		'\x2', '\x2', '\x2', '\xDC', '#', '\x3', '\x2', '\x2', '\x2', '\xDD',
+		'\xDF', '\a', '\x10', '\x2', '\x2', '\xDE', '\xE0', '\x5', '(', '\x15',
+		'\x2', '\xDF', '\xDE', '\x3', '\x2', '\x2', '\x2', '\xDF', '\xE0', '\x3',
+		'\x2', '\x2', '\x2', '\xE0', '\xEA', '\x3', '\x2', '\x2', '\x2', '\xE1',
+		'\xE3', '\a', '\x11', '\x2', '\x2', '\xE2', '\xE4', '\x5', '(', '\x15',
+		'\x2', '\xE3', '\xE2', '\x3', '\x2', '\x2', '\x2', '\xE3', '\xE4', '\x3',
+		'\x2', '\x2', '\x2', '\xE4', '\xEA', '\x3', '\x2', '\x2', '\x2', '\xE5',
+		'\xE7', '\a', '\x12', '\x2', '\x2', '\xE6', '\xE8', '\x5', '(', '\x15',
+		'\x2', '\xE7', '\xE6', '\x3', '\x2', '\x2', '\x2', '\xE7', '\xE8', '\x3',
+		'\x2', '\x2', '\x2', '\xE8', '\xEA', '\x3', '\x2', '\x2', '\x2', '\xE9',
+		'\xDD', '\x3', '\x2', '\x2', '\x2', '\xE9', '\xE1', '\x3', '\x2', '\x2',
+		'\x2', '\xE9', '\xE5', '\x3', '\x2', '\x2', '\x2', '\xEA', '%', '\x3',
+		'\x2', '\x2', '\x2', '\xEB', '\xEE', '\x5', '*', '\x16', '\x2', '\xEC',
+		'\xED', '\a', '\x14', '\x2', '\x2', '\xED', '\xEF', '\x5', '(', '\x15',
+		'\x2', '\xEE', '\xEC', '\x3', '\x2', '\x2', '\x2', '\xEE', '\xEF', '\x3',
+		'\x2', '\x2', '\x2', '\xEF', '\'', '\x3', '\x2', '\x2', '\x2', '\xF0',
+		'\xF3', '\x5', '\xE', '\b', '\x2', '\xF1', '\xF3', '\x5', '*', '\x16',
+		'\x2', '\xF2', '\xF0', '\x3', '\x2', '\x2', '\x2', '\xF2', '\xF1', '\x3',
+		'\x2', '\x2', '\x2', '\xF3', ')', '\x3', '\x2', '\x2', '\x2', '\xF4',
+		'\xF5', '\a', '\x17', '\x2', '\x2', '\xF5', '\x101', '\x5', '\xE', '\b',
+		'\x2', '\xF6', '\xF7', '\a', '\x18', '\x2', '\x2', '\xF7', '\x101', '\x5',
+		'\xE', '\b', '\x2', '\xF8', '\xF9', '\a', '\x19', '\x2', '\x2', '\xF9',
+		'\x101', '\x5', '\xE', '\b', '\x2', '\xFA', '\xFB', '\a', '\x1A', '\x2',
+		'\x2', '\xFB', '\x101', '\x5', '\xE', '\b', '\x2', '\xFC', '\xFD', '\a',
+		'\x1B', '\x2', '\x2', '\xFD', '\x101', '\x5', '\xE', '\b', '\x2', '\xFE',
+		'\xFF', '\a', '\x1C', '\x2', '\x2', '\xFF', '\x101', '\x5', '\xE', '\b',
+		'\x2', '\x100', '\xF4', '\x3', '\x2', '\x2', '\x2', '\x100', '\xF6', '\x3',
+		'\x2', '\x2', '\x2', '\x100', '\xF8', '\x3', '\x2', '\x2', '\x2', '\x100',
+		'\xFA', '\x3', '\x2', '\x2', '\x2', '\x100', '\xFC', '\x3', '\x2', '\x2',
+		'\x2', '\x100', '\xFE', '\x3', '\x2', '\x2', '\x2', '\x101', '+', '\x3',
+		'\x2', '\x2', '\x2', '\x102', '\x105', '\a', '\x15', '\x2', '\x2', '\x103',
+		'\x105', '\a', '\x16', '\x2', '\x2', '\x104', '\x102', '\x3', '\x2', '\x2',
+		'\x2', '\x104', '\x103', '\x3', '\x2', '\x2', '\x2', '\x105', '-', '\x3',
+		'\x2', '\x2', '\x2', '\x106', '\x107', '\a', '\x13', '\x2', '\x2', '\x107',
+		'\x10A', '\x5', '(', '\x15', '\x2', '\x108', '\x109', '\a', '\x14', '\x2',
+		'\x2', '\x109', '\x10B', '\x5', '(', '\x15', '\x2', '\x10A', '\x108',
+		'\x3', '\x2', '\x2', '\x2', '\x10A', '\x10B', '\x3', '\x2', '\x2', '\x2',
+		'\x10B', '/', '\x3', '\x2', '\x2', '\x2', '#', '\x34', '?', '\x41', 'M',
+		'O', 'X', '_', '\x62', 'h', '|', '\x84', '\x8A', '\x8E', '\x98', '\x9E',
+		'\xA6', '\xAC', '\xB3', '\xB8', '\xBE', '\xC1', '\xC9', '\xD5', '\xDB',
+		'\xDF', '\xE3', '\xE7', '\xE9', '\xEE', '\xF2', '\x100', '\x104', '\x10A',
 	};

 	public static readonly ATN _ATN =


Methods loading added and implementation added

--- DirectOutputCSharpWrapper/DirectOutput.cs
+++ DirectOutputCSharpWrapper/DirectOutput.cs
@@ -1,36 +1,133 @@
 using System;
 using Microsoft.Win32;

-namespace DirectOutputCSharpWrapper
-{
-    public class DirectOutput
-    {
-        private const String directOutputKey = "SOFTWARE\\Saitek\\DirectOutput";
+using System.IO;
+using System.Text;
+using System.Runtime.InteropServices;

-        public bool isActive
-        {
-            get
-            {
-                return libraryPath != null;
-            }
-        }
+namespace DirectOutputCSharpWrapper {

-        String libraryPath = null;
+	public class RegistryKeyNotFound : Exception {
+		public RegistryKeyNotFound() : base(@"HKEY_LOCAL_MACHINE\SOFTWARE\Saitek\DirectOutput key not found.") {}
+	}

-        public DirectOutput()
-        {
-            RegistryKey key = Registry.LocalMachine.OpenSubKey(directOutputKey);
-            if (key == null)
-            {
-                // No Key - No Game)
-                return;
-            }
+	public class RegistryValueNotFound : Exception {
+		public RegistryValueNotFound() : base(@"DirectOutput value in key HKEY_LOCAL_MACHINE\SOFTWARE\Saitek\DirectOutput not found.") {}
+	}

-            object value = key.GetValue("DirectOutput");
-            if (value != null && value is String)
-            {
-                libraryPath = (String)value;
-            }
-        }
-    }
+	public class DirectOutput {
+
+		struct SRequestStatus {
+			Int32 dwHeaderError;
+			Int32 dwHeaderInfo;
+			Int32 dwRequestError;
+			Int32 dwRequestInfo;
+		};
+
+		// Callbacks
+		public delegate void EnumerateCallback(IntPtr hDevice, IntPtr pvContext);
+		public delegate void DeviceCallback(IntPtr hDevice, bool bAdded, IntPtr pvContext);
+		public delegate void SoftButtonCallback(IntPtr hDevice, UInt32 buttons, IntPtr pvContext);
+		public delegate void PageCallback(IntPtr hDevice, bool bActivated, IntPtr pvContext);
+
+		// Library functions
+		private delegate Int32 Initialize([MarshalAsAttribute(UnmanagedType.LPWStr)] string appName);
+		private delegate Int32 Deinitialize();
+		private delegate Int32 RegisterDeviceCallback([MarshalAs(UnmanagedType.FunctionPtr)]DeviceCallback callback, IntPtr target);
+		private delegate Int32 Enumerate([MarshalAs(UnmanagedType.FunctionPtr)]EnumerateCallback callback, IntPtr target);
+		private delegate Int32 GetDeviceType(IntPtr hDevice, out Guid pGuidType);
+		private delegate Int32 GetDeviceInstance(IntPtr hDevice, out Guid pGuidInstance);
+		private delegate Int32 SetProfile(IntPtr hDevice, Int32 fileNameLength, [MarshalAsAttribute(UnmanagedType.LPWStr)] string filename);
+		private delegate Int32 RegisterSoftButtonCallback(IntPtr hDevice, [MarshalAs(UnmanagedType.FunctionPtr)]SoftButtonCallback callback, IntPtr target);
+		private delegate Int32 RegisterPageCallback(IntPtr hDevice, [MarshalAs(UnmanagedType.FunctionPtr)]PageCallback callback, IntPtr target);
+		private delegate Int32 AddPage(IntPtr hDevice, Int32 dwPage, [MarshalAsAttribute(UnmanagedType.LPWStr)] string wszName, Int32 dwFlags);
+		private delegate Int32 RemovePage(IntPtr hDevice, Int32 dwPage);
+		private delegate Int32 SetLed(IntPtr hDevice, Int32 dwPage, Int32 dwIndex, Int32 dwValue);
+		private delegate Int32 SetString(IntPtr hDevice, Int32 dwPage, Int32 dwIndex, Int32 cchValue, [MarshalAsAttribute(UnmanagedType.LPWStr)] string wszValue);
+		private delegate Int32 SetImage(IntPtr hDevice, Int32 dwPage, Int32 dwIndex, Int32 cbValue, byte[] pbValue);
+		private delegate Int32 SetImageFromFile(IntPtr hDevice, Int32 dwPage, Int32 dwIndex, Int32 fileNameLength, [MarshalAsAttribute(UnmanagedType.LPWStr)] string filename);
+		private delegate Int32 StartServer(IntPtr hDevice, Int32 fileNameLength, [MarshalAsAttribute(UnmanagedType.LPWStr)] string filename, out IntPtr pdwServerId, out SRequestStatus psStatus);
+		private delegate Int32 CloseServer(IntPtr hDevice, Int32 dwServerId, out SRequestStatus psStatus);
+		private delegate Int32 SendServerMsg(IntPtr hDevice, Int32 dwServerId, Int32 dwRequest, Int32 dwPage, Int32 cbIn, IntPtr pvIn, Int32 cbOut, out IntPtr pvOut, out SRequestStatus psStatus);
+		private delegate Int32 SendServerFile(IntPtr hDevice, Int32 dwServerId, Int32 dwRequest, Int32 dwPage, Int32 cbInHdr, IntPtr pvInHdr, Int32 fileNameLength, [MarshalAsAttribute(UnmanagedType.LPWStr)] string filename, Int32 cbOut, out IntPtr pvOut, out SRequestStatus psStatus);
+		private delegate Int32 SaveFile(IntPtr hDevice, Int32 dwPage, Int32 dwFile, Int32 fileNameLength, [MarshalAsAttribute(UnmanagedType.LPWStr)] string filename, out SRequestStatus psStatus);
+		private delegate Int32 DisplayFile(IntPtr hDevice, Int32 dwPage, Int32 dwIndex, Int32 dwFile, out SRequestStatus psStatus);
+		private delegate Int32 DeleteFile(IntPtr hDevice, Int32 dwPage, Int32 dwFile, out SRequestStatus psStatus);
+
+		// Functions placeholders
+		private Initialize initialize;
+		private Deinitialize deinitialize;
+		private RegisterDeviceCallback registerDeviceCallback;
+		private Enumerate enumerate;
+		private GetDeviceType getDeviceType;
+		private GetDeviceInstance getDeviceInstance;
+		private SetProfile setProfile;
+		private RegisterSoftButtonCallback registerSoftButtonCallback;
+		private RegisterPageCallback registerPageCallback;
+		private AddPage addPage;
+		private RemovePage removePage;
+		private SetLed setLed;
+		private SetString setString;
+		private SetImage setImage;
+		private SetImageFromFile setImageFromFile;
+		private StartServer startServer;
+		private CloseServer closeServer;
+		private SendServerMsg sendServerMsg;
+		private SendServerFile sendServerFile;
+		private SaveFile saveFile;
+		private DisplayFile displayFile;
+		private DeleteFile deleteFile;
+
+		private const String directOutputKey = "SOFTWARE\\Saitek\\DirectOutput";
+
+		private GCHandle thisHandle;
+		private UInt32 hModule;
+
+		public DirectOutput() {
+			thisHandle = GCHandle.Alloc(this);
+
+			RegistryKey key = Registry.LocalMachine.OpenSubKey(directOutputKey);
+			if (key == null) {
+				throw new RegistryKeyNotFound();
+			}
+
+			object value = key.GetValue("DirectOutput");
+			if ((value == null) || !(value is String)) {
+				throw new RegistryValueNotFound();
+			}
+
+			hModule = DllHelper.LoadLibrary((String)value);
+
+			// Initialize functions
+			initialize = DllHelper.GetFunction<Initialize>(hModule, "DirectOutput_Initialize");
+			deinitialize = DllHelper.GetFunction<Deinitialize>(hModule, "DirectOutput_Deinitialize");
+			registerDeviceCallback = DllHelper.GetFunction<RegisterDeviceCallback>(hModule, "DirectOutput_RegisterDeviceCallback");
+			enumerate = DllHelper.GetFunction<Enumerate>(hModule, "DirectOutput_Enumerate");
+			getDeviceType = DllHelper.GetFunction<GetDeviceType>(hModule, "DirectOutput_GetDeviceType");
+			getDeviceInstance = DllHelper.GetFunction<GetDeviceInstance>(hModule, "DirectOutput_GetDeviceInstance");
+			setProfile = DllHelper.GetFunction<SetProfile>(hModule, "DirectOutput_SetProfile");
+			registerSoftButtonCallback = DllHelper.GetFunction<RegisterSoftButtonCallback>(hModule, "DirectOutput_RegisterSoftButtonCallback");
+			registerPageCallback = DllHelper.GetFunction<RegisterPageCallback>(hModule, "DirectOutput_RegisterPageCallback");
+			addPage = DllHelper.GetFunction<AddPage>(hModule, "DirectOutput_AddPage");
+			removePage = DllHelper.GetFunction<RemovePage>(hModule, "DirectOutput_RemovePage");
+			setLed = DllHelper.GetFunction<SetLed>(hModule, "DirectOutput_SetLed");
+			setString = DllHelper.GetFunction<SetString>(hModule, "DirectOutput_SetString");
+			setImage = DllHelper.GetFunction<SetImage>(hModule, "DirectOutput_SetImage");
+			setImageFromFile = DllHelper.GetFunction<SetImageFromFile>(hModule, "DirectOutput_SetImageFromFile");
+			startServer = DllHelper.GetFunction<StartServer>(hModule, "DirectOutput_StartServer");
+			closeServer = DllHelper.GetFunction<CloseServer>(hModule, "DirectOutput_CloseServer");
+			sendServerMsg = DllHelper.GetFunction<SendServerMsg>(hModule, "DirectOutput_SendServerMsg");
+			sendServerFile = DllHelper.GetFunction<SendServerFile>(hModule, "DirectOutput_SendServerFile");
+			saveFile = DllHelper.GetFunction<SaveFile>(hModule, "DirectOutput_SaveFile");
+			displayFile = DllHelper.GetFunction<DisplayFile>(hModule, "DirectOutput_DisplayFile");
+			deleteFile = DllHelper.GetFunction<DeleteFile>(hModule, "DirectOutput_DeleteFile");
+		}
+
+		~DirectOutput() {
+			DllHelper.FreeLibrary(hModule);
+			thisHandle.Free();
+		}
+
+	}
+
 }


Refactor NumberEncoderService to match algorithms in EOSERV source more closely

The way the algorithms are written in EOSERV is much more readable. I also got the original algorithms from a decompiled C# DLL, so I'll let the compiler do any further optimization.

--- EOLib.IO/Services/NumberEncoderService.cs
+++ EOLib.IO/Services/NumberEncoderService.cs
@@ -1,6 +1,8 @@
 // Original Work Copyright (c) Ethan Moffat 2014-2016
 // This file is subject to the GPL v2 License
 // For additional details, see the LICENSE file
+
+using System.Linq;

 namespace EOLib.IO.Services
 {
@@ -8,24 +10,32 @@
     {
         public byte[] EncodeNumber(int number, int size)
         {
-            byte[] numArray = new byte[size];
-            for (int index = 3; index >= 1; --index)
+            var numArray = Enumerable.Repeat(254, 4).ToArray();
+            var original = number;
+
+            if (original >= NumericConstants.THREE_BYTE_MAX)
             {
-                if (index >= numArray.Length)
-                {
-                    if (number >= NumericConstants.NUMERIC_MAXIMUM[index - 1])
-                        number %= NumericConstants.NUMERIC_MAXIMUM[index - 1];
-                }
-                else if (number >= NumericConstants.NUMERIC_MAXIMUM[index - 1])
-                {
-                    numArray[index] = (byte)(number / NumericConstants.NUMERIC_MAXIMUM[index - 1] + 1);
-                    number %= NumericConstants.NUMERIC_MAXIMUM[index - 1];
-                }
-                else
-                    numArray[index] = 254;
+                numArray[3] = number/NumericConstants.THREE_BYTE_MAX + 1;
+                number = number%NumericConstants.THREE_BYTE_MAX;
             }
-            numArray[0] = (byte)(number + 1);
-            return numArray;
+
+            if (original >= NumericConstants.TWO_BYTE_MAX)
+            {
+                numArray[2] = number/NumericConstants.TWO_BYTE_MAX + 1;
+                number = number%NumericConstants.TWO_BYTE_MAX;
+            }
+
+            if (original >= NumericConstants.ONE_BYTE_MAX)
+            {
+                numArray[1] = number/NumericConstants.ONE_BYTE_MAX + 1;
+                number = number%NumericConstants.ONE_BYTE_MAX;
+            }
+
+            numArray[0] = number + 1;
+
+            return numArray.Select(x => (byte)x)
+                           .Take(size)
+                           .ToArray();
         }

         public int DecodeNumber(params byte[] b)
@@ -39,10 +49,15 @@
                 --b[index];
             }

-            int num = 0;
-            for (int index = b.Length - 1; index >= 1; --index)
-                num += b[index] * NumericConstants.NUMERIC_MAXIMUM[index - 1];
-            return num + b[0];
+            var retNum = 0;
+            if (b.Length > 3)
+                retNum += b[3]*NumericConstants.THREE_BYTE_MAX;
+            if (b.Length > 2)
+                retNum += b[2]*NumericConstants.TWO_BYTE_MAX;
+            if (b.Length > 1)
+                retNum += b[1]*NumericConstants.ONE_BYTE_MAX;
+
+            return retNum + b[0];
         }
     }
 }


Move primary star caching to StarScan.Process

--- EliteDangerous/EliteDangerous/StarScan.cs
+++ EliteDangerous/EliteDangerous/StarScan.cs
@@ -203,24 +203,6 @@

             if (je.IsStar && je.BodyName == system && je.nOrbitalPeriod != null)
             {
-                if (!primaryStarScans.ContainsKey(system))
-                {
-                    primaryStarScans[system] = new List<JournalScan>();
-                }
-
-                if (!primaryStarScans[system].Any(s => CompareEpsilon(s.nAge, je.nAge) &&
-                                                       CompareEpsilon(s.nEccentricity, je.nEccentricity) &&
-                                                       CompareEpsilon(s.nOrbitalInclination, je.nOrbitalInclination) &&
-                                                       CompareEpsilon(s.nOrbitalPeriod, je.nOrbitalPeriod) &&
-                                                       CompareEpsilon(s.nPeriapsis, je.nPeriapsis) &&
-                                                       CompareEpsilon(s.nRadius, je.nRadius) &&
-                                                       CompareEpsilon(s.nRotationPeriod, je.nRotationPeriod) &&
-                                                       CompareEpsilon(s.nSemiMajorAxis, je.nSemiMajorAxis) &&
-                                                       CompareEpsilon(s.nStellarMass, je.nStellarMass)))
-                {
-                    primaryStarScans[system].Add(je);
-                }
-
                 return system + " A";
             }

@@ -499,6 +481,29 @@
                 }
             }
         }
+
+        private void CachePrimaryStar(JournalScan je, ISystem sys)
+        {
+            string system = sys.name;
+
+            if (!primaryStarScans.ContainsKey(system))
+            {
+                primaryStarScans[system] = new List<JournalScan>();
+            }
+
+            if (!primaryStarScans[system].Any(s => CompareEpsilon(s.nAge, je.nAge) &&
+                                                   CompareEpsilon(s.nEccentricity, je.nEccentricity) &&
+                                                   CompareEpsilon(s.nOrbitalInclination, je.nOrbitalInclination) &&
+                                                   CompareEpsilon(s.nOrbitalPeriod, je.nOrbitalPeriod) &&
+                                                   CompareEpsilon(s.nPeriapsis, je.nPeriapsis) &&
+                                                   CompareEpsilon(s.nRadius, je.nRadius) &&
+                                                   CompareEpsilon(s.nRotationPeriod, je.nRotationPeriod) &&
+                                                   CompareEpsilon(s.nSemiMajorAxis, je.nSemiMajorAxis) &&
+                                                   CompareEpsilon(s.nStellarMass, je.nStellarMass)))
+            {
+                primaryStarScans[system].Add(je);
+            }
+        }
         #endregion

         public bool Process(JournalScan sc, ISystem sys, bool reprocessPrimary = false)           // FALSE if you can't process it
@@ -536,14 +541,23 @@
             // Process elements
             ScanNode node = ProcessElements(sc, sys, sn, customname, elements, starscannodetype, isbeltcluster);

+            // Process top-level star
             if (elements.Count == 1)
             {
                 // Process any belts if present
                 ProcessBelts(sc, node);

-                // Reprocess if we've encountered the primary (A) star and we already have a "Main Star"
-                if (reprocessPrimary && elements[0].Equals("A", StringComparison.InvariantCultureIgnoreCase) && sn.starnodes.Any(n => n.Key.Length > 1 && n.Value.type == ScanNodeType.star))
-                    ReProcess(sn);
+                // Process primary star in multi-star system
+                if (elements[0].Equals("A", StringComparison.InvariantCultureIgnoreCase))
+                {
+                    CachePrimaryStar(sc, sys);
+
+                    // Reprocess if we've encountered the primary (A) star and we already have a "Main Star"
+                    if (reprocessPrimary && sn.starnodes.Any(n => n.Key.Length > 1 && n.Value.type == ScanNodeType.star))
+                    {
+                        ReProcess(sn);
+                    }
+                }
             }

             return true;


Fix serverlist mod.

Fix serverlist mod.

--- serverlist/main.cs
+++ serverlist/main.cs
@@ -45,7 +45,7 @@
     if(%status $= "done")
     {
         printServers();
-        //quit();
+        quit();
     }
 }


some tidying up and fuller comments; no logic changes

--- src/i18n/LocalizingService.cs
+++ src/i18n/LocalizingService.cs
@@ -91,16 +91,16 @@
             {
                 var culture = GetCultureInfoFromLanguage(language);

-                // en-US
-                var regional = TryGetTextFor(culture.IetfLanguageTag, key);
-
                 // Save cycles processing beyond the default; just return the original key
                 if (culture.TwoLetterISOLanguageName.Equals(DefaultSettings.DefaultTwoLetterISOLanguageName, StringComparison.OrdinalIgnoreCase))
                 {
                     return key;
                 }

-                // en (and regional was defined)
+                // E.g. en-US
+                var regional = TryGetTextFor(culture.IetfLanguageTag, key);
+
+                // If we just tried a region-specific lookup and that failed...try a region-neutral lookup. E.g. fr-CH -> fr.
                 if(!culture.IetfLanguageTag.Equals(culture.TwoLetterISOLanguageName, StringComparison.OrdinalIgnoreCase) && regional == key)
                 {
                     var global = TryGetTextFor(culture.TwoLetterISOLanguageName, key);


Cleaned up

Cleaned up

--- LatestVersion.cs
+++ LatestVersion.cs
@@ -1,8 +1,6 @@
 using System;
-using System.Diagnostics;
 using System.IO;
 using System.Net;
-using System.Text.RegularExpressions;
 using System.Windows.Forms;
 using HtmlDocument = HtmlAgilityPack.HtmlDocument;

@@ -11,33 +9,23 @@
     class LatestVersion
     {
         public delegate void GotVersionInfo(object sender, string version);
-        public LatestVersion() {
+
+        public static Version CurrentVersion{
+            get { return new Version(Application.ProductVersion); }
         }
-
-        public static Version CurrentVersion
-        {
-            get { return new Version(Application.ProductVersion); }
-            set { }
-        }
-

         public String ErrorMessage { get; set; }
         public String LatestStableRelease { get; set; }

         public async void GetLatestStableVersion(GotVersionInfo callback) {
-
             var client = new WebClient();
-
             try {
                 byte[] bytes =
-                    await
-                    client.DownloadDataTaskAsync(
+                    await client.DownloadDataTaskAsync(
                         "http://mcec.codeplex.com/wikipage?title=Latest%20Stable%20Version%20Number");

-                Stream s = new MemoryStream(bytes);
-
                 var htmlDoc = new HtmlDocument();
-                htmlDoc.Load(s);
+                htmlDoc.Load(new MemoryStream(bytes));

                 var div = htmlDoc.DocumentNode.SelectSingleNode("//*/div[@class='wikidoc']");
                 if (div != null)
@@ -48,22 +36,16 @@
             }
             catch (Exception e) {
                 ErrorMessage = e.Message;
-                Debug.Write(e.Message);
             }
             callback(this, LatestStableRelease);
         }

-        /// <summary>
-        /// > 0 - Newer version available
-        /// = 0 - Same version
-        /// < 0 - Current version is newer.
-        /// </summary>
-        /// <returns></returns>
+        // > 0 - Newer version available
+        // = 0 - Same version
+        // < 0 - Current version is newer
         public int CompareVersions() {
             var latest = new Version(LatestStableRelease);
-
             return CurrentVersion.CompareTo(latest);
         }
-
     }
 }


Fix conflict.

Fix conflict.

--- Lyon/GameForm.cs
+++ Lyon/GameForm.cs
@@ -26,6 +26,11 @@
             Shown += (sender, e) => { Initialize(new Context(GetCoreConfiguration(), source)); };
         }

+        private string FileFilters
+            =>
+                "Game Worlds (*.zzt;*.szt)|*.zzt;*.szt;*.ZZT;*.SZT|ZZT Worlds (*.zzt)|*.zzt;*.ZZT|Super ZZT Worlds (*.SZT)|*.szt;*.SZT|Saved Games (*.sav)|*.sav;*.SAV|All Openable Files (*.zzt;*.szt;*.sav)|*.zzt;*.szt;*.sav;*.ZZT;*.SZT;*.SAV|All Files (*.*)|*.*"
+            ;
+
         private IContext Context { get; set; }

         private void CommonSetup()
@@ -37,7 +42,6 @@
             InitializeComponent();
             InitializeEvents();

-            // Load the appropriate terminal.
             _terminal = new Roton.WinForms.OpenGL.Terminal(new OpenGl3())
             {
                 Top = 0,
@@ -48,6 +52,7 @@
                 TerminalFont = font1,
                 TerminalPalette = palette1
             };
+
             mainPanel.Controls.Add((UserControl) _terminal);

             // Used to help Mono's WinForm implementation set the correct window size
@@ -119,7 +124,7 @@

         private void OpenWorld()
         {
-            var ofd = new OpenWorldDialog();
+            var ofd = new OpenFileDialog {Filter = FileFilters};
             if (ofd.ShowDialog() == DialogResult.OK)
             {
                 Initialize(new Context(GetCoreConfiguration(), File.ReadAllBytes(ofd.FileName)));
@@ -130,9 +135,10 @@
         {
             if (Context != null)
             {
-                var sfd = new SaveWorldDialog();
-                if (sfd.ShowDialog(Context.WorldData) == DialogResult.OK)
+                var sfd = new SaveFileDialog {Filter = FileFilters};
+                if (sfd.ShowDialog() == DialogResult.OK)
                 {
+                    //Initialize(new Context(sfd.FileName, false));
                     Context.Save(sfd.FileName);
                 }
             }


use local machine registry again, because currentUser does not work for wrapper

--- MachineConfig.cs
+++ MachineConfig.cs
@@ -18,7 +18,6 @@
         private static bool Has64BitJRE {
             get {
                 RegistryKey local64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
-                RegistryKey currentUser = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64);
                 RegistryKey jreKey64 = local64.OpenSubKey(JRERegistryKey);
                 RegistryKey jreKey6410 = local64.OpenSubKey(JRE10RegistryKey);
                 if (jreKey64 != null && (string)jreKey64.GetValue(@"FakeKeyForFreenet") != @"true") {
@@ -26,7 +25,7 @@
                 }
                 if (jreKey6410 != null) {
                     // create old style registry key to get the wrapper to work
-                    jreKey64 = currentUser.CreateSubKey(JRERegistryKey);
+                    jreKey64 = local64.CreateSubKey(JRERegistryKey);
                     // to distinguish from real entry, so we can keep it up to date over external Java updates (see above)
                     jreKey64.SetValue(@"FakeKeyForFreenet", @"true", RegistryValueKind.String);
                     jreKey64.SetValue(@"CurrentVersion",jreKey6410.GetValue(@"CurrentVersion") );
@@ -34,6 +33,10 @@
                     jreKey64ForVersion.SetValue(
                         @"JavaHome",
                         jreKey6410.OpenSubKey(Convert.ToString(jreKey6410.GetValue(@"CurrentVersion"))).GetValue(@"JavaHome"),
+                        RegistryValueKind.ExpandString);
+                    jreKey64ForVersion.SetValue(
+                        @"RuntimeLib",
+                        jreKey6410.OpenSubKey(Convert.ToString(jreKey6410.GetValue(@"CurrentVersion"))).GetValue(@"RuntimeLib"),
                         RegistryValueKind.ExpandString);
                     return true;
                 }


lower volume

lower volume

--- Game1.cs
+++ Game1.cs
@@ -86,6 +86,7 @@

 			MediaPlayer.IsRepeating = true;
 			MediaPlayer.Play (BackgroundMusic);
+			MediaPlayer.Volume = 0.1f;
         }

 		protected void spawnRocks() {


Add support for null and nullable values.

--- Test.csx
+++ Test.csx
@@ -13,7 +13,7 @@
     var search = 5;

     //c.Find(x => x.Foo == searchString);
-    c.Find(x => x.Bar == false);
+    c.Find(x => x.Foo == null);
 }

 class Client<DocumentType>
@@ -21,6 +21,11 @@
     public void Find(Expression<Func<DocumentType, bool>> expression)
     {
         var bod = expression.Body as BinaryExpression;
+
+		if (bod == null)
+		{
+			throw new ArgumentException($"Invalid expression. Expression must be in the form of e.g. x => x.Foo == 5 and must use the document parameter passed in.");
+		}

         Console.WriteLine("Binary Expression Type: {0}", bod.NodeType);
         Console.WriteLine("Method to be called: {0}", bod.Method);
@@ -30,7 +35,12 @@
     }

     static string ValueToString(object memberValue)
-    {
+	{
+		if (memberValue == null)
+		{
+			return $"null";
+		}
+
         Type t = memberValue.GetType();

         if (t == typeof(string))
@@ -82,7 +92,12 @@

             case ExpressionType.MemberAccess:
                 return GetMemberValue((MemberExpression) exp);
-
+
+			case ExpressionType.Convert:
+				var unary = (UnaryExpression) exp;
+
+				return GetExpressionValue(unary.Operand);
+
             default: throw new ArgumentException($"Expression type {exp.NodeType} is invalid.");
         }
     }
@@ -122,4 +137,6 @@
     public bool Bar { get; set; }

     public int Baz { get; set; }
+
+	public int? Bat { get; set; }
 }


Types that has documented fields/methods needs at least an empty summary

--- Hooks.cs
+++ Hooks.cs
@@ -14,6 +14,9 @@
     using Logger = Core.Logger;
     using Steamworks;

+    /// <summary>
+    ///
+    /// </summary>
     public class Hooks : Core.Hooks
     {
         internal static List<string> hookNames = new List<string>() {


Constant Update

Constant Update

--- ImageMagickSharp/Global/Constants.cs
+++ ImageMagickSharp/Global/Constants.cs
@@ -17,8 +17,7 @@
 		internal const CallingConvention WandCallingConvention = CallingConvention.Cdecl;

 		/// <summary> The wand library. </summary>
-		//internal const string WandLibrary = @"ImageMagickLib\CORE_RL_Wand_.dll";
-		internal const string WandLibrary = @"C:\DevRepository\ImageMagickSharp\ImageMagickSharp.Tests\bin\Debug\CORE_RL_Wand_.dll";
+		internal const string WandLibrary = @"CORE_RL_Wand_.dll";

 		/// <summary> The magick false. </summary>
 		internal const  int MagickFalse = 0;


Fix Simplify method (which needs only Simplified sink and not a full GeometrySink), as per:

http://msdn.microsoft.com/en-us/library/windows/desktop/dd742770(v=vs.85).aspx

--- Source/SharpDX.Direct2D1/Geometry.cs
+++ Source/SharpDX.Direct2D1/Geometry.cs
@@ -335,7 +335,7 @@
         /// <param name="geometrySink"> The <see cref="SharpDX.Direct2D1.SimplifiedGeometrySink"/> to which the simplified geometry is appended. </param>
         /// <returns>If the method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.</returns>
         /// <unmanaged>HRESULT Simplify([None] D2D1_GEOMETRY_SIMPLIFICATION_OPTION simplificationOption,[In, Optional] const D2D1_MATRIX_3X2_F* worldTransform,[None] FLOAT flatteningTolerance,[In] ID2D1SimplifiedGeometrySink* geometrySink)</unmanaged>
-        public void Simplify(SharpDX.Direct2D1.GeometrySimplificationOption simplificationOption, GeometrySink geometrySink)
+        public void Simplify(SharpDX.Direct2D1.GeometrySimplificationOption simplificationOption, SimplifiedGeometrySink geometrySink)
         {
             Simplify(simplificationOption, null, FlatteningTolerance, geometrySink);
         }
@@ -348,7 +348,7 @@
         /// <param name="geometrySink"> The <see cref="SharpDX.Direct2D1.SimplifiedGeometrySink"/> to which the simplified geometry is appended. </param>
         /// <returns>If the method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.</returns>
         /// <unmanaged>HRESULT Simplify([None] D2D1_GEOMETRY_SIMPLIFICATION_OPTION simplificationOption,[In, Optional] const D2D1_MATRIX_3X2_F* worldTransform,[None] FLOAT flatteningTolerance,[In] ID2D1SimplifiedGeometrySink* geometrySink)</unmanaged>
-        public void Simplify(SharpDX.Direct2D1.GeometrySimplificationOption simplificationOption, float flatteningTolerance, GeometrySink geometrySink)
+        public void Simplify(SharpDX.Direct2D1.GeometrySimplificationOption simplificationOption, float flatteningTolerance, SimplifiedGeometrySink geometrySink)
         {
             Simplify(simplificationOption, null, flatteningTolerance, geometrySink);
         }
@@ -362,7 +362,7 @@
         /// <param name="geometrySink"> The <see cref="SharpDX.Direct2D1.SimplifiedGeometrySink"/> to which the simplified geometry is appended. </param>
         /// <returns>If the method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.</returns>
         /// <unmanaged>HRESULT Simplify([None] D2D1_GEOMETRY_SIMPLIFICATION_OPTION simplificationOption,[In, Optional] const D2D1_MATRIX_3X2_F* worldTransform,[None] FLOAT flatteningTolerance,[In] ID2D1SimplifiedGeometrySink* geometrySink)</unmanaged>
-        public void Simplify(SharpDX.Direct2D1.GeometrySimplificationOption simplificationOption, SharpDX.Matrix3x2? worldTransform, float flatteningTolerance, GeometrySink geometrySink)
+        public void Simplify(SharpDX.Direct2D1.GeometrySimplificationOption simplificationOption, SharpDX.Matrix3x2? worldTransform, float flatteningTolerance, SimplifiedGeometrySink geometrySink)
         {
             this.Simplify_(simplificationOption, worldTransform, flatteningTolerance, GeometrySinkShadow.ToIntPtr(geometrySink));
         }


only check hash when file exists

only check hash when file exists

--- Tocsoft.GraphQLCodeGen.MsBuild/GenerateGraphQLClient.cs
+++ Tocsoft.GraphQLCodeGen.MsBuild/GenerateGraphQLClient.cs
@@ -103,21 +103,22 @@
                     string fileName = Path.GetFileName(f);
                     string newFileContent = File.ReadAllText(f);
                     string hashFile = Path.Combine(fullIntermediateOutputDirectory, fileName + ".hash");
+                    string targetPath = Path.Combine(fullIntermediateOutputDirectory, fileName);
+
                     bool filedirty = true;
                     string actualHash = GetSha256Hash(sha, newFileContent); // TODO skip section while hashing (generated date etc)
-                    if (File.Exists(hashFile))
+                    if (File.Exists(hashFile) && File.Exists(targetPath)) // ensure we only try and skip if files exist on disk
                     {
                         string hash = File.ReadAllText(hashFile);
                         filedirty = hash != actualHash;
                     }
-                    File.WriteAllText(hashFile, actualHash);

-                    string targetPAth = Path.Combine(fullIntermediateOutputDirectory, fileName);
                     if (filedirty)
                     {
-                        File.WriteAllText(targetPAth, newFileContent);
+                        File.WriteAllText(hashFile, actualHash);
+                        File.WriteAllText(targetPath, newFileContent);
                     }
-                    generateFiles.Add(new TaskItem(targetPAth));
+                    generateFiles.Add(new TaskItem(targetPath));
                 }
                 // find matching files in this folder if they have identical hashes then skip them


bugfix saving village comments

bugfix saving village comments

--- TribalWars/Controls/Accordeon/Details/DetailsControl.cs
+++ TribalWars/Controls/Accordeon/Details/DetailsControl.cs
@@ -373,6 +373,8 @@
                     DetailsGrid.SelectedObject = new ExtendedVillageDescriptor(command.Village);
                     Table.DisplayReports(command.Village, command.Village.Reports);
                     SetButtons(command.Village.Type);
+
+                    _current = command; // HACK: The textchanged eventhandler of comments would overwrite the old village comment with the new one
                     Comments.Text = command.Village.Comments;

                     World.Default.Map.EventPublisher.SelectVillages(null, command.Village, VillageTools.Notes);


Add unit test

Add unit test

--- UnitTestUsefullFunctions/UnitTestFunctionsMathPrimes.cs
+++ UnitTestUsefullFunctions/UnitTestFunctionsMathPrimes.cs
@@ -1597,6 +1597,15 @@
     public void TestMethod_IsPrime_911()
     {
       const int source = 911;
+      const bool expected = true;
+      bool result = FunctionsMath.IsPrime(source);
+      Assert.AreEqual(result, expected);
+    }
+
+    [TestMethod]
+    public void TestMethod_IsPrime_919()
+    {
+      const int source = 919;
       const bool expected = true;
       bool result = FunctionsMath.IsPrime(source);
       Assert.AreEqual(result, expected);


Add unit test

Add unit test

--- UnitTestUsefullFunctions/UnitTestFunctionsMathPrimes.cs
+++ UnitTestUsefullFunctions/UnitTestFunctionsMathPrimes.cs
@@ -2174,6 +2174,15 @@
         public void TestMethod_IsPrime_1381()
         {
             const int source = 1381;
+            const bool expected = true;
+            bool result = FunctionsMath.IsPrime(source);
+            Assert.AreEqual(result, expected);
+        }
+
+        [TestMethod]
+        public void TestMethod_IsPrime_1399()
+        {
+            const int source = 1399;
             const bool expected = true;
             bool result = FunctionsMath.IsPrime(source);
             Assert.AreEqual(result, expected);


Twitch Quote formatting

Twitch Quote formatting

--- JefBot/Commands/MigoPluginCommand.cs
+++ JefBot/Commands/MigoPluginCommand.cs
@@ -99,7 +99,11 @@
                 if (command.ArgumentsAsList.Count == 0)
                 {
                     Quote qu = migo();
-                    string q = $"{qu.Quotestring} QuoteID:{qu.id}";
+                    if (qu.SubmittedBy == null || qu.SubmittedBy == "")
+                    {
+                        qu.SubmittedBy = "Unknown";
+                    }
+                    string q = $"{qu.Quotestring} submitted by {qu.SubmittedBy} #{qu.id}";
                     client.SendMessage(command.ChatMessage.Channel, q);
                 }
                 else


Fix a crash when loading some animations (#429)

* Fix crash when loading some files with animation

* Load skeleton nodes correctly

* pr feedback

--- UnityGLTF/Assets/UnityGLTF/Scripts/GLTFSceneImporter.cs
+++ UnityGLTF/Assets/UnityGLTF/Scripts/GLTFSceneImporter.cs
@@ -652,6 +652,16 @@
 			progress?.Report(progressStatus);
 		}

+		private async Task<BufferCacheData> GetBufferData(BufferId bufferId)
+		{
+			if (_assetCache.BufferCache[bufferId.Id] == null)
+			{
+				await ConstructBuffer(bufferId.Value, bufferId.Id);
+			}
+
+			return _assetCache.BufferCache[bufferId.Id];
+		}
+
 		protected async Task ConstructBuffer(GLTFBuffer buffer, int bufferIndex)
 		{
 			if (buffer.Uri == null)
@@ -766,21 +776,15 @@
 				Dictionary<string, AttributeAccessor> attributeAccessors = new Dictionary<string, AttributeAccessor>(primitive.Attributes.Count + 1);
 				foreach (var attributePair in primitive.Attributes)
 				{
-					BufferId bufferIdPair = attributePair.Value.Value.BufferView.Value.Buffer;
-					GLTFBuffer buffer = bufferIdPair.Value;
-					int bufferId = bufferIdPair.Id;
-
-					// on cache miss, load the buffer
-					if (_assetCache.BufferCache[bufferId] == null)
-					{
-						await ConstructBuffer(buffer, bufferId);
-					}
+					var bufferId = attributePair.Value.Value.BufferView.Value.Buffer;
+
+					var bufferData = await GetBufferData(bufferId);

 					AttributeAccessor attributeAccessor = new AttributeAccessor
 					{
 						AccessorId = attributePair.Value,
-						Stream = _assetCache.BufferCache[bufferId].Stream,
-						Offset = (uint)_assetCache.BufferCache[bufferId].ChunkOffset
+						Stream = bufferData.Stream,
+						Offset = (uint)bufferData.ChunkOffset
 					};

 					attributeAccessors[attributePair.Key] = attributeAccessor;
@@ -788,18 +792,14 @@

 				if (primitive.Indices != null)
 				{
-					int bufferId = primitive.Indices.Value.BufferView.Value.Buffer.Id;
-
-					if (_assetCache.BufferCache[bufferId] == null)
-					{
-						await ConstructBuffer(primitive.Indices.Value.BufferView.Value.Buffer.Value, bufferId);
-					}
+					var bufferId = primitive.Indices.Value.BufferView.Value.Buffer;
+					var bufferData = await GetBufferData(bufferId);

 					AttributeAccessor indexBuilder = new AttributeAccessor
 					{
 						AccessorId = primitive.Indices,
-						Stream = _assetCache.BufferCache[bufferId].Stream,
-						Offset = (uint)_assetCache.BufferCache[bufferId].ChunkOffset
+						Stream = bufferData.Stream,
+						Offset = (uint)bufferData.ChunkOffset
 					};

 					attributeAccessors[SemanticProperties.INDICES] = indexBuilder;
@@ -864,7 +864,7 @@
 			throw new Exception("no RelativePath");
 		}

-		protected virtual void BuildAnimationSamplers(GLTFAnimation animation, int animationId)
+		protected virtual async Task BuildAnimationSamplers(GLTFAnimation animation, int animationId)
 		{
 			// look up expected data types
 			var typeMap = new Dictionary<int, string>();
@@ -890,24 +890,24 @@
 				var samplerDef = animation.Samplers[i];

 				// set up input accessors
-				BufferCacheData bufferCacheData = _assetCache.BufferCache[samplerDef.Input.Value.BufferView.Value.Buffer.Id];
+				BufferCacheData inputBufferCacheData = await GetBufferData(samplerDef.Input.Value.BufferView.Value.Buffer);
 				AttributeAccessor attributeAccessor = new AttributeAccessor
 				{
 					AccessorId = samplerDef.Input,
-					Stream = bufferCacheData.Stream,
-					Offset = bufferCacheData.ChunkOffset
+					Stream = inputBufferCacheData.Stream,
+					Offset = inputBufferCacheData.ChunkOffset
 				};

 				samplers[i].Input = attributeAccessor;
 				samplersByType["time"].Add(attributeAccessor);

 				// set up output accessors
-				bufferCacheData = _assetCache.BufferCache[samplerDef.Output.Value.BufferView.Value.Buffer.Id];
+				BufferCacheData outputBufferCacheData = await GetBufferData(samplerDef.Output.Value.BufferView.Value.Buffer);
 				attributeAccessor = new AttributeAccessor
 				{
 					AccessorId = samplerDef.Output,
-					Stream = bufferCacheData.Stream,
-					Offset = bufferCacheData.ChunkOffset
+					Stream = outputBufferCacheData.Stream,
+					Offset = outputBufferCacheData.ChunkOffset
 				};

 				samplers[i].Output = attributeAccessor;
@@ -968,7 +968,7 @@
 			}
 		}

-		protected AnimationClip ConstructClip(Transform root, GameObject[] nodes, int animationId)
+		protected async Task<AnimationClip> ConstructClip(Transform root, int animationId, CancellationToken cancellationToken)
 		{
 			GLTFAnimation animation = _gltfRoot.Animations[animationId];

@@ -984,7 +984,7 @@
 			}

 			// unpack accessors
-			BuildAnimationSamplers(animation, animationId);
+			await BuildAnimationSamplers(animation, animationId);

 			// init clip
 			AnimationClip clip = new AnimationClip
@@ -999,8 +999,8 @@
 			foreach (AnimationChannel channel in animation.Channels)
 			{
 				AnimationSamplerCacheData samplerCache = animationCache.Samplers[channel.Sampler.Id];
-				Transform node = nodes[channel.Target.Node.Id].transform;
-				string relativePath = RelativePathFrom(node, root);
+				var node = await GetNode(channel.Target.Node, cancellationToken);
+				string relativePath = RelativePathFrom(node.transform, root);

 				NumericArray input = samplerCache.Input.AccessorContent,
 					output = samplerCache.Output.AccessorContent;
@@ -1154,7 +1154,7 @@
 			{
 				NodeId node = scene.Nodes[i];
 				await _LoadNode(node.Id, cancellationToken);
-				GameObject nodeObj = _assetCache.NodeCache[node.Id];
+				GameObject nodeObj = await GetNode(node, cancellationToken);
 				nodeObj.transform.SetParent(sceneObj.transform, false);
 				nodeTransforms[i] = nodeObj.transform;
 			}
@@ -1165,7 +1165,7 @@
 				Animation animation = sceneObj.AddComponent<Animation>();
 				for (int i = 0; i < _gltfRoot.Animations.Count; ++i)
 				{
-					AnimationClip clip = ConstructClip(sceneObj.transform, _assetCache.NodeCache, i);
+					AnimationClip clip = await ConstructClip(sceneObj.transform, i, cancellationToken);

 					clip.wrapMode = WrapMode.Loop;

@@ -1181,6 +1181,15 @@
 			InitializeGltfTopLevelObject();
 		}

+		private async Task<GameObject> GetNode(NodeId nodeId, CancellationToken cancellationToken)
+		{
+			if (_assetCache.NodeCache[nodeId.Id] == null)
+			{
+				await ConstructNode(nodeId.Value, nodeId.Id, cancellationToken);
+			}
+
+			return _assetCache.NodeCache[nodeId.Id];
+		}

 		protected virtual async Task ConstructNode(Node node, int nodeIndex, CancellationToken cancellationToken)
 		{
@@ -1222,9 +1231,7 @@
 			{
 				foreach (var child in node.Children)
 				{
-					// todo blgross: replace with an iterartive solution
-					await ConstructNode(child.Value, child.Id, cancellationToken);
-					GameObject childObj = _assetCache.NodeCache[child.Id];
+					GameObject childObj = await GetNode(child, cancellationToken);
 					childObj.transform.SetParent(nodeObj.transform, false);
 				}
 			}
@@ -1311,7 +1318,7 @@
 			return primitive.Targets != null;
 		}

-		protected virtual async Task SetupBones(Skin skin, MeshPrimitive primitive, SkinnedMeshRenderer renderer, GameObject primitiveObj, Mesh curMesh)
+		protected virtual async Task SetupBones(Skin skin, MeshPrimitive primitive, SkinnedMeshRenderer renderer, GameObject primitiveObj, Mesh curMesh, CancellationToken cancellationToken)
 		{
 			var boneCount = skin.Joints.Count;
 			Transform[] bones = new Transform[boneCount];
@@ -1331,15 +1338,17 @@

 			for (int i = 0; i < boneCount; i++)
 			{
-				if (_assetCache.NodeCache[skin.Joints[i].Id] == null)
-				{
-					await ConstructNode(_gltfRoot.Nodes[skin.Joints[i].Id], skin.Joints[i].Id, CancellationToken.None);
-				}
-				bones[i] = _assetCache.NodeCache[skin.Joints[i].Id].transform;
+				var node = await GetNode(skin.Joints[i], cancellationToken);
+
+				bones[i] = node.transform;
 				bindPoses[i] = gltfBindPoses[i].ToUnityMatrix4x4Convert();
 			}

-			renderer.rootBone = _assetCache.NodeCache[skin.Skeleton.Id].transform;
+			if (skin.Skeleton != null)
+			{
+				var rootBoneNode = await GetNode(skin.Skeleton, cancellationToken);
+				renderer.rootBone = rootBoneNode.transform;
+			}
 			curMesh.bindposes = bindPoses;
 			renderer.bones = bones;
 		}
@@ -1417,7 +1426,7 @@
 					//	SetupBlendShapes(primitive);
 					if (HasBones(skin))
 					{
-						await SetupBones(skin, primitive, skinnedMeshRenderer, primitiveObj, curMesh);
+						await SetupBones(skin, primitive, skinnedMeshRenderer, primitiveObj, curMesh, cancellationToken);
 						cancellationToken.ThrowIfCancellationRequested();
 					}


Avoiding comparison to empty string

Avoiding comparison to empty string

--- Framework.Core/Theraot/Core/PathHelper.cs
+++ Framework.Core/Theraot/Core/PathHelper.cs
@@ -204,7 +204,7 @@
             {
                 throw new ArgumentNullException("path");
             }
-            if (path == string.Empty)
+            if (path.Length == 0)
             {
                 return false;
             }


Disable de-jitter

Disable de-jitter

--- Fusion/Engine/Client/GameClient.Active.cs
+++ Fusion/Engine/Client/GameClient.Active.cs
@@ -1,4 +1,5 @@
-using System;
+//#define USE_DEJITTER
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -38,7 +39,9 @@
 				queue	=	new SnapshotQueue(32);
 				queue.Push( new Snapshot( new TimeSpan(0), snapshotId, initialSnapshot) );

+				#if USE_DEJITTER
 				jitter		=	new JitterBuffer( gameClient.Game, svTicks );
+				#endif
 				stopwatch	=	new Stopwatch();
 				stopwatch.Start();
 				clientTicks	=	0;
@@ -83,18 +86,18 @@

 				clientTicks	+=	gameTime.Elapsed.Ticks;

-
 				//
 				//	Feed snapshot from jitter buffer :
 				//
+				#if USE_DEJITTER
 				uint ackCmdID;
 				byte[] snapshot = jitter.Pop( clientTicks, playoutDelay, out ackCmdID );

 				if (snapshot!=null) {
+					gameClient.FeedSnapshot( snapshot, ackCmdID );
+				}
+				#endif

-					gameClient.FeedSnapshot( snapshot, ackCmdID );
-
-				}

 				//
 				//	Update client state and get user command:
@@ -138,7 +141,11 @@
 			/// <param name="svTicks"></param>
 			void FeedSnapshot ( byte[] snapshot, uint ackCmdID, long svTicks )
 			{
+				#if USE_DEJITTER
 				jitter.Push( snapshot, ackCmdID, svTicks, stopwatch.Elapsed.Ticks );
+				#else
+				gameClient.FeedSnapshot( snapshot, ackCmdID );
+				#endif
 			}


fixed file still complaining about line endings

--- BlogTemplate/Pages/Drafts.cshtml
+++ BlogTemplate/Pages/Drafts.cshtml
@@ -1,21 +1,21 @@
-@page
-@model DraftsModel
-@{
-    ViewData["Title"] = "Drafts";
-}
-
@ViewData["Title"]

-
-
This is where you go to edit drafts.

-
-@{
-    foreach (var post in Model.Posts)
-    {
-        if (!post.IsPublic)
-        {
-

-
@post.Title

-
@post.Excerpt

-

-        }
-    }
+@page
+@model DraftsModel
+@{
+    ViewData["Title"] = "Drafts";
 }
+
@ViewData["Title"]

+
+
This is where you go to edit drafts.

+
+@{
+    foreach (var post in Model.Posts)
+    {
+        if (!post.IsPublic)
+        {
+

+
@post.Title

+
@post.Excerpt

+

+        }
+    }
+}


fix issue on incorrect click for GotoMyAccountPage

--- Golem.PageObjects.Cael/HeaderComponent.cs
+++ Golem.PageObjects.Cael/HeaderComponent.cs
@@ -30,7 +30,7 @@

         public ContactInfoPage GoToMyAccountPage()
         {
-            SignOut_Link.Click();
+            MyAccount_Link.Click();
             return new ContactInfoPage();
         }


Check for updates

Check for updates

--- ModStatistics.cs
+++ ModStatistics.cs
@@ -1,6 +1,7 @@
 using JsonFx.Json;
 using System;
 using System.Collections.Generic;
+using System.Collections.Specialized;
 using System.IO;
 using System.Linq;
 using System.Net;
@@ -68,6 +69,9 @@
                     Debug.LogWarning("[ModStatistics] Could not parse ID");
                     createConfig(configpath);
                 }
+
+                var str = node.GetValue("update");
+                if (str != null) { bool.TryParse(str, out update); }
             }

             running = true;
@@ -79,6 +83,7 @@
             }

             sendReports();
+            checkUpdates();
         }

         private void createConfig(string configpath)
@@ -111,6 +116,7 @@
         }

         private bool running = false;
+        private bool update = true;

         private Guid id;
         private GameScenes? scene = null;
@@ -197,6 +203,69 @@
                         Debug.LogWarning(String.Format("[ModStatistics] Error initiating {0) upload:\n{1}", Path.GetFileName(file), e));
                     }
                 }
+            }
+        }
+
+        private class ManifestEntry
+        {
+            public string url = String.Empty;
+            public string path = String.Empty;
+        }
+
+        private void checkUpdates()
+        {
+            if (!update) { return; }
+
+            using (var client = new WebClient())
+            {
+                client.DownloadStringCompleted += (s, e) =>
+                {
+                    if (e.Cancelled)
+                    {
+                        Debug.LogWarning(String.Format("[ModStatistics] Update query operation was cancelled"));
+                    }
+                    else if (e.Error != null)
+                    {
+                        Debug.LogError(String.Format("[ModStatistics] Could not query for updates:\n{0}", e.Error));
+                    }
+                    else
+                    {
+                        try
+                        {
+                            var manifest = new JsonReader().Read<ManifestEntry[]>(e.Result);
+                            foreach (var entry in manifest)
+                            {
+                                var dest = folder + Path.DirectorySeparatorChar + entry.path;
+                                Directory.CreateDirectory(Path.GetDirectoryName(dest));
+                                client.DownloadFileAsync(new Uri(entry.url), dest, entry);
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            Debug.LogError(String.Format("[ModStatistics] Error parsing update manifest:\n{0}", ex));
+                        }
+                    }
+                };
+
+                client.DownloadFileCompleted += (s, e) =>
+                {
+                    var entry = e.UserState as ManifestEntry;
+                    if (e.Cancelled)
+                    {
+                        Debug.LogWarning(String.Format("[ModStatistics] Update download operation was cancelled"));
+                    }
+                    else if (e.Error != null)
+                    {
+                        Debug.LogError(String.Format("[ModStatistics] Could not download update for {0}:\n{1}", entry.path, e.Error));
+                    }
+                    else
+                    {
+                        Debug.Log("[ModStatistics] Successfully updated " + entry.path);
+                    }
+                };
+
+                client.Headers.Add(HttpRequestHeader.UserAgent, String.Format("ModStatistics/{0} ({1})", getInformationalVersion(Assembly.GetExecutingAssembly()), version));
+                client.DownloadStringAsync(new Uri(@"http://stats.majiir.net/update"));
             }
         }


Use Application.OpenURL instead of reflecting on Process.Start

--- ModStatistics.cs
+++ ModStatistics.cs
@@ -105,7 +105,7 @@
                     "ModStatistics",
                     HighLogic.Skin,
                     new DialogOption("OK", () => { writeConfig(); checkUpdates(); }, true),
-                    new DialogOption("Launch Website", () => { startProcess(@"http://stats.majiir.net/"); })
+                    new DialogOption("Launch Website", () => { Application.OpenURL(@"http://stats.majiir.net/"); })
                     ),
                 true,
                 HighLogic.Skin
@@ -438,10 +438,5 @@
                 return Platform.Windows;
             }
         }
-
-        private static void startProcess(string process)
-        {
-            Type.GetType("System.Diagnostics.Process").GetMethod("Start", new Type[] { typeof(String) }).Invoke(null, new[] { process });
-        }
     }
 }


Switched private set

Switched private set

--- CoCSharp/Networking/PacketReceivedEventArgs.cs
+++ CoCSharp/Networking/PacketReceivedEventArgs.cs
@@ -11,7 +11,7 @@
             Exception = ex;
         }

-        public IPacket Packet { get; set; }
-        public Exception Exception { get; set; }
+        public IPacket Packet { get; private set; }
+        public Exception Exception { get; private set; }
     }
 }


Added some null checks

Added some null checks

--- Client/Systems/VesselProtoSys/VesselProtoSystem.cs
+++ Client/Systems/VesselProtoSys/VesselProtoSystem.cs
@@ -157,11 +157,11 @@
         /// </summary>
         private void CheckVesselsToLoadReloadWhileNotInFlight()
         {
-            if (Enabled && Time.timeSinceLevelLoad > 1f && HighLogic.LoadedScene == GameScenes.SPACECENTER)
-            {
-                var currentVesselIds = HighLogic.CurrentGame.flightState.protoVessels.Select(v => v.vesselID);
-                var missingVessels = VesselsProtoStore.AllPlayerVessels.Values
-                    .Where(p => !currentVesselIds.Contains(p.VesselId)).Select(v => v.ProtoVessel);
+            if (Enabled && Time.timeSinceLevelLoad > 1f && HighLogic.LoadedScene == GameScenes.SPACECENTER && HighLogic.CurrentGame?.flightState?.protoVessels != null)
+            {
+                var currentVesselIds = HighLogic.CurrentGame?.flightState?.protoVessels?.Select(v => v.vesselID);
+                var missingVessels = VesselsProtoStore.AllPlayerVessels.Values.Where(p => !currentVesselIds.Contains(p.VesselId) && p.ProtoVessel != null)
+                    .Select(v => v.ProtoVessel);
                 HighLogic.CurrentGame.flightState.protoVessels.AddRange(missingVessels);
             }
         }
@@ -199,7 +199,7 @@
         }

         private List<Guid> VesselsToReload { get; } = new List<Guid>();
-
+
         /// <summary>
         /// Check vessels that must be reloaded
         /// </summary>
@@ -243,7 +243,7 @@
         }

         #endregion
-
+
         #region Private

         private static string GetInvalidVesselParts(Vessel checkVessel)


Some extra validation

Some extra validation

--- Commencement.Mvc/Controllers/PetitionController.cs
+++ Commencement.Mvc/Controllers/PetitionController.cs
@@ -352,7 +352,7 @@
                 {
                     ModelState.AddModelError("ExtraTicketPetition", string.Format("Our records indicate that you have already submitted a petition for {0}", a.Ceremony.CeremonyName));
                 }
-                else if (string.IsNullOrEmpty(a.Reason))
+                else if (string.IsNullOrWhiteSpace(a.Reason))
                 {
                     ModelState.AddModelError(string.Format("Reason{0}", a.Ceremony.Id), string.Format("Reason cannot be blank for petition {0}", a.Ceremony.CeremonyName));
                 }


btn styling

btn styling

--- Commencement.Mvc/Views/Shared/_LogonPartial.cshtml
+++ Commencement.Mvc/Views/Shared/_LogonPartial.cshtml
@@ -1,15 +1,16 @@
 @if (Request.IsAuthenticated)
 {
-    if ((bool?) HttpContext.Current.Session["Emulation"] == null || (bool?) HttpContext.Current.Session["Emulation"] == false)
+
+    if ((bool?)HttpContext.Current.Session["Emulation"] == null || (bool?)HttpContext.Current.Session["Emulation"] == false)
     {
-        @Html.ActionLink("Log Off", "LogOut", "Account", null, htmlAttributes: new { @class = "btn btn-18 btn-blue" })
+        @Html.ActionLink("Log Off", "LogOut", "Account", null, htmlAttributes: new { @class = "btn btn-14 btn-sm btn-log" })
     }
     else
     {
-        @Html.ActionLink("End Emulation", "EndEmulate", "Account", null, htmlAttributes: new { @class = "btn btn-18 btn-red" })
+        @Html.ActionLink("End Emulation", "EndEmulate", "Account", null, htmlAttributes: new { @class = "btn btn-14 btn-sm btn-red" })
     }
 }
 else
 {
-    @Html.ActionLink("Log On", "LogOn", "Account", null, htmlAttributes: new { @class = "btn btn-18 btn-blue" })
+    @Html.ActionLink("Log On", "LogOn", "Account", null, htmlAttributes: new { @class = "btn btn-14 btn-log btn-sm" })
 }


prepare v1.7
if resource doesn't exists, don't throw exceptions, but use .ToString() method

git-svn-id: e8c7700c11386a21c3a380c8741ce182329511ac@4942 463e38ab-4f4e-0410-907a-65d2b3888964

--- I/TypeConverter/LocalizedEnumConverter.cs
+++ I/TypeConverter/LocalizedEnumConverter.cs
@@ -19,6 +19,8 @@
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Globalization;
+using System.Linq;
+using System.Reflection;
 using System.Resources;

 #endregion
@@ -58,8 +60,11 @@
         public LocalizedEnumConverter(Type enumType)
             : base(enumType)
         {
-            string resourceBaseName = string.Format(CultureInfo.InvariantCulture, "{0}.Properties.Resources", enumType.Assembly.GetName().Name);
-            m_ResourceManager = new ResourceManager(resourceBaseName, enumType.Assembly);
+            Assembly assembly = enumType.Assembly;
+            string resourceBaseName = string.Format(CultureInfo.InvariantCulture, "{0}.Properties.Resources", assembly.GetName().Name);
+            m_ResourceManager = assembly.GetManifestResourceNames().Any(o => o.StartsWith(resourceBaseName))
+                                    ? new ResourceManager(resourceBaseName, enumType.Assembly)
+                                    : null;

             m_LookupTable = new Dictionary<string, object>();
             ICollection standardValues = GetStandardValues();
@@ -180,9 +185,13 @@
         {
             if (value != null)
             {
-                Type type = value.GetType();
-                string resourceName = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", type.Name, value);
-                return m_ResourceManager.GetString(resourceName, ci) ?? value.ToString();
+                if (m_ResourceManager != null)
+                {
+                    Type type = value.GetType();
+                    string resourceName = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", type.Name, value);
+                    return m_ResourceManager.GetString(resourceName, ci) ?? value.ToString();
+                }
+                return value.ToString();
             }
             return string.Empty;
         }


Grad Images for register page only

Grad Images for register page only

--- Commencement.Mvc/Views/Student/RegisterTest.cshtml
+++ Commencement.Mvc/Views/Student/RegisterTest.cshtml
@@ -83,8 +83,7 @@

                 <form action="">

-                        <input type="checkbox"> I Authorize my information be provided to GradImages
-
+                        <input id="gradTrack" name="gradTrack" type="checkbox" value="true"> I Authorize my information be provided to GradImages

                 </form>