@@ -143,47 +143,40 @@ internal ForgeInfo(Json.JSONData data, FMLVersion fmlVersion)
143
143
case FMLVersion . FML3 :
144
144
// Example ModInfo for Minecraft 1.18 and greater (FML3)
145
145
146
- // {
147
- // "enforcesSecureChat": true,
148
- // "forgeData": {
149
- // "channels": [],
150
- // "mods": [],
151
- // "truncated": false, // legacy versions see truncated lists, modern versions ignore this truncated flag (binary data has its own)
152
- // "fmlNetworkVersion": 3,
153
- // "d": "ȳ\u0000\u0000ࠨ㐤獋㙖⹌ᦘ̺⸱恤䒸⡑⛧沮婙㨹牥ఈㄵচ₀沮婙㨹牥ఈㄵচ倠岙㜲獥䋊㷍᭳ႇׇ㘴娘▅筳ص䰭宛㘲、\u0000ᠸጋ囗湌夜㘲杩棐䐱ᅱ挃☥ోᤗ㌮ఀ䬣 坖ɍ䮌ᤘ\r\n旉䠳ዣ◆䲌㜃瑥廮ⷉࠋ–䁠奚Ҵ㔱摜䂸ᅱ獳ౠᡚ㜷汥戊䂸űဓĠ嵛㖱数嫤Ǎ塰䛶ⶎᮚ㞳晲擞ᖝ″ዣ䘆ఋʂ潦令ඕ爈䖔⺁ᥚ⾹潳棤㦥ᬻ挐䅀㠹楬ۨ㣄উ瀀渀嬛㘼扩搢䃀熁挂♥\r\n墋㒺摬牜ࣜ䁠嘗湌孛㜴浩惂䠙熙排٥孁㒰ͮ屢Ӏ䠐⚐䷮ᣛ㊴瑳戚䢸熁匒إܴ䫜巑፻ᚷؠ䀀ㆃ牵䋨㦥ࠫ㋣䗆䂌㨈慲䫬ᖱᮓᘧ汬尚ㆰ٫屲㣄ᆉ恳ಭ川㤷፫擨妅挫♖乮塘 㖱慰\r\n囆䓩\t"
154
- // },
155
- // "description": {
156
- // "text": "A Minecraft Server"
157
- // },
158
- // "players": {
159
- // "max": 100,
160
- // "online": 0
161
- // },
162
- // "version": {
163
- // "name": "1.20.1",
164
- // "protocol": 763
165
- // }
166
- // }
167
-
168
- // All buffer data are encoded and write to forgeData["d"]
146
+ // "forgeData": {
147
+ // "channels": [],
148
+ // "mods": [],
149
+ // "truncated": false, // legacy versions see truncated lists, modern versions ignore this truncated flag (binary data has its own)
150
+ // "fmlNetworkVersion": 3,
151
+ // "d": "ȳ\u0000\u0000ࠨ㐤獋㙖⹌ᦘ̺⸱恤䒸⡑⛧沮婙㨹牥ఈㄵচ₀沮婙㨹牥ఈㄵচ倠岙㜲獥䋊㷍᭳ႇׇ㘴娘▅筳ص䰭宛㘲、\u0000ᠸጋ囗湌夜㘲杩棐䐱ᅱ挃☥ోᤗ㌮ఀ䬣 坖ɍ䮌ᤘ\r\n旉䠳ዣ◆䲌㜃瑥廮ⷉࠋ–䁠奚Ҵ㔱摜䂸ᅱ獳ౠᡚ㜷汥戊䂸űဓĠ嵛㖱数嫤Ǎ塰䛶ⶎᮚ㞳晲擞ᖝ″ዣ䘆ఋʂ潦令ඕ爈䖔⺁ᥚ⾹潳棤㦥ᬻ挐䅀㠹楬ۨ㣄উ瀀渀嬛㘼扩搢䃀熁挂♥\r\n墋㒺摬牜ࣜ䁠嘗湌孛㜴浩惂䠙熙排٥孁㒰ͮ屢Ӏ䠐⚐䷮ᣛ㊴瑳戚䢸熁匒إܴ䫜巑፻ᚷؠ䀀ㆃ牵䋨㦥ࠫ㋣䗆䂌㨈慲䫬ᖱᮓᘧ汬尚ㆰ٫屲㣄ᆉ恳ಭ川㤷፫擨妅挫♖乮塘 㖱慰\r\n囆䓩\t"
152
+ // }
153
+
154
+ // 1.18 and greater, the mod list and channel list is compressed to forgeData["d"] for efficiency,
155
+ // - Here is how forge encode and decode them:
169
156
// https://github.com/MinecraftForge/MinecraftForge/blob/cb12df41e13da576b781be695f80728b9594c25f/src/main/java/net/minecraftforge/network/ServerStatusPing.java#L264
170
-
171
- // 1.18 and greater, the buffer is encoded for efficiency
157
+ // - Here is the discussion:
172
158
// see https://github.com/MinecraftForge/MinecraftForge/pull/8169
173
159
174
160
string encodedData = data . Properties [ "d" ] . StringValue ;
175
161
Queue < byte > dataPackage = decodeOptimized ( encodedData ) ;
176
162
DataTypes dataTypes = new DataTypes ( Protocol18Handler . MC_1_18_1_Version ) ;
177
163
178
164
//
179
- // [truncated][boolean] placeholder for whether we are truncating
180
- // [Mod Size][unsigned short] short so that we can replace it later in case of truncation
165
+ // [ Truncated ][ Bool ] // Unused
166
+ // [ Mod Size ][ Unsigned short ]
181
167
//
182
- bool truncated = dataTypes . ReadNextBool ( dataPackage ) ;
168
+ dataTypes . ReadNextBool ( dataPackage ) ; // truncated: boolean
183
169
var modsSize = dataTypes . ReadNextUShort ( dataPackage ) ;
184
170
185
- Dictionary < string , string > channels = new ( ) ;
186
171
Dictionary < string , string > mods = new ( ) ;
172
+ // Mod Array Definition:
173
+ // [ Channel Size And Version Flag ][ VarInt ] // If the value at bit Mask 0x01 is 1, The Mod Version will be ignore.
174
+ // // The one-right-shifted int is the Channel List size.
175
+ // [ Mod Id ][ String ]
176
+ // [ Mod Version ][ Optional String ] // Depends on the Flag above
177
+ // [ Channel List ][ Array ] [ Channel Name ][ String ]
178
+ // [ Channel Version ][ String ]
179
+ // [ Required On Client ][ Bool ]
187
180
188
181
for ( var i = 0 ; i < modsSize ; i ++ ) {
189
182
var channelSizeAndVersionFlag = dataTypes . ReadNextVarInt ( dataPackage ) ;
@@ -194,38 +187,42 @@ internal ForgeInfo(Json.JSONData data, FMLVersion fmlVersion)
194
187
195
188
var modId = dataTypes . ReadNextString ( dataPackage ) ;
196
189
197
- string IGNORESERVERONLY = "" ; // it was "OHNOES\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31 ";
190
+ string IGNORESERVERONLY = "IGNORED " ;
198
191
var modVersion = isIgnoreServerOnly ? IGNORESERVERONLY : dataTypes . ReadNextString ( dataPackage ) ;
199
192
200
193
for ( var i1 = 0 ; i1 < channelSize ; i1 ++ ) {
201
- var channelName = dataTypes . ReadNextString ( dataPackage ) ;
202
- var channelVersion = dataTypes . ReadNextString ( dataPackage ) ;
203
- var requiredOnClient = dataTypes . ReadNextBool ( dataPackage ) ;
204
- channels . Add ( modId + ":" + channelName , channelVersion + ":" + requiredOnClient ) ;
194
+ dataTypes . ReadNextString ( dataPackage ) ; // channelName
195
+ dataTypes . ReadNextString ( dataPackage ) ; // channelVersion
196
+ dataTypes . ReadNextBool ( dataPackage ) ; // requiredOnClient
205
197
}
206
198
207
199
mods . Add ( modId , modVersion ) ;
208
200
Mods . Add ( new ForgeMod ( modId , modVersion ) ) ;
209
201
}
210
202
211
- var nonModChannelCount = dataTypes . ReadNextVarInt ( dataPackage ) ;
212
- for ( var i = 0 ; i < nonModChannelCount ; i ++ ) {
213
- var channelName = dataTypes . ReadNextString ( dataPackage ) ;
214
- var channelVersion = dataTypes . ReadNextString ( dataPackage ) ;
215
- var requiredOnClient = dataTypes . ReadNextBool ( dataPackage ) ;
216
- channels . Add ( channelName , channelVersion + ":" + requiredOnClient ) ;
217
- }
203
+ // Ignore the left data, which is NonMod Channel List
204
+ // [ nonMod Channel Count ][ VarInt ]
205
+ // [ nonMod Channel List ][ Array ] [ Channel Name ][ String ]
206
+ // [ Channel Version ][ Bool ]
207
+ // [ Required On Client ][ Bool ]
218
208
219
209
break ;
220
210
default :
221
211
throw new NotImplementedException ( "FMLVersion '" + fmlVersion + "' not implemented!" ) ;
222
212
}
223
213
}
224
214
225
- // https://github.com/MinecraftForge/MinecraftForge/blob/cb12df41e13da576b781be695f80728b9594c25f/src/main/java/net/minecraftforge/network/ServerStatusPing.java#L361
226
- // Decode binary data ForgeData["d"] to Queue<byte>
215
+ /// <summary>
216
+ /// Decompress binary data ForgeData["d"] (FML 3)
217
+ /// </summary>
218
+ /// <param name="encodedData">The encoded data.</param>
219
+ /// <returns>Decoded forge data Queue<byte>.</returns>
220
+ /// <para>
221
+ /// 1.18 and greater, the mod list and channel list is compressed for efficiency
222
+ /// The code below is converted from forge source code, see:
223
+ /// https://github.com/MinecraftForge/MinecraftForge/blob/cb12df41e13da576b781be695f80728b9594c25f/src/main/java/net/minecraftforge/network/ServerStatusPing.java#L361
224
+ /// </para>
227
225
private static Queue < byte > decodeOptimized ( string encodedData ) {
228
- // Console.WriteLine("Got encoded data:" + encodedData + ", decoding...");
229
226
int size0 = encodedData [ 0 ] ;
230
227
int size1 = encodedData [ 1 ] ;
231
228
int size = size0 | ( size1 << 15 ) ;
0 commit comments