Sure I can explain
Obfuscation.
Obfuscated classes are classfiles which have been intentionally modified to make the code which they're performing unreadable to human eyes in case it's being decompiled.
This for instance is the decompiled code of an obfuscated classfile from UP3 RC4:
package com.maddox.il2.builder;
import com.maddox.gwindow.GRegion;
import com.maddox.gwindow.GWindow;
import com.maddox.gwindow.GWindowButton;
import com.maddox.gwindow.GWindowDialogClient;
import com.maddox.gwindow.GWindowFramed;
import com.maddox.gwindow.GWindowTable;
import java.util.ArrayList;
public class yh extends GWindowFramed
{
private ni a;
private GWindowButton b;
private PlMapLoad c;
public yh()
{
doNew(Plugin.builder.clientWindow, 2.0F, 2.0F, 25.0F, 40.0F, true);
this.bSizable = true;
}
public void afterCreated()
{
super.afterCreated();
close(false);
}
public void windowShown()
{
super.windowShown();
if (this.a != null)
this.a.resolutionChanged();
}
public void windowHidden()
{
super.windowHidden();
}
public void created()
{
this.bAlwaysOnTop = true;
super.created();
this.title = Plugin.i18n("mds.loadMaps.windowTitle");
this.clientWindow = create(new ee(this));
GWindowDialogClient localGWindowDialogClient = (GWindowDialogClient)this.clientWindow;
this.a = new ni(this, localGWindowDialogClient, Plugin.i18n("mds.loadMaps.listTitle"), 1.0F, 3.0F, 15.0F, 20.0F);
localGWindowDialogClient.addControl(this.b = new t(this, localGWindowDialogClient, 17.0F, 8.0F, 5.0F, 2.0F, Plugin.i18n("mds.loadMaps.loadMap"), null));
}
private void a(GWindow paramGWindow)
{
float f1 = paramGWindow.win.dx;
float f2 = paramGWindow.win.dy;
this.a.setPosSize(5.0F, 5.0F, f1 - 10.0F, f2 - 40.0F);
this.b.setPosSize(5.0F, f2 - 25.0F, f1 - 10.0F, 20.0F);
}
private void a()
{
if (this.c != null)
this.c.zutiExecute(this.a.selectRow);
}
public void close(boolean paramBoolean)
{
super.close(paramBoolean);
}
public void a(String paramString)
{
this.title = (Plugin.i18n("mds.loadMaps.windowTitle") + " - " + paramString);
}
public void b()
{
if (this.a.a != null)
this.a.a.clear();
}
public void a(ArrayList paramArrayList)
{
int i = paramArrayList.size();
int j = 0;
if (Plugin.a);
while (j < i)
{
PlMapLoad.Land localLand = (PlMapLoad.Land)paramArrayList.get(j);
this.a.a.add(localLand.i18nName);
j++;
}
}
public void a(PlMapLoad paramPlMapLoad)
{
this.c = paramPlMapLoad;
}
static void a(yh paramyh, GWindow paramGWindow)
{
paramyh.a(paramGWindow);
}
static void a(yh paramyh)
{
paramyh.a();
}
}
...and this is the "unobfuscated", or better said the original code of the same class:
package com.maddox.il2.builder;
import java.util.ArrayList;
import com.maddox.gwindow.GWindow;
import com.maddox.gwindow.GWindowButton;
import com.maddox.gwindow.GWindowDialogClient;
import com.maddox.gwindow.GWindowTable;
import com.maddox.gwindow.GWindowFramed;
import com.maddox.il2.builder.PlMapLoad.Land;
public class Zuti_WMapsList extends GWindowFramed
{
private Table lstMaps;
private GWindowButton bLoadMap;
private PlMapLoad plMapLoad;
class Table extends GWindowTable
{
public ArrayList lst = new ArrayList();
public int countRows()
{
return lst != null ? lst.size() : 0;
}
public Object getValueAt(int i, int i_0_)
{
if (lst == null)
return null;
if (i < 0 || i >= lst.size())
return null;
String string = (String) lst.get(i);
return string;
}
public void resolutionChanged()
{
vSB.scroll = rowHeight(0);
super.resolutionChanged();
}
public Table(GWindow gwindow, String string, float f, float f_1_, float f_2_, float f_3_)
{
super(gwindow, f, f_1_, f_2_, f_3_);
bColumnsSizable = false;
addColumn(string, null);
vSB.scroll = rowHeight(0);
resized();
}
}
public Zuti_WMapsList()
{
doNew(Plugin.builder.clientWindow, 2.0F, 2.0F, 25.0F, 40.0F, true);
bSizable = true;
}
public void afterCreated()
{
super.afterCreated();
close(false);
}
public void windowShown()
{
super.windowShown();
if(lstMaps != null)
lstMaps.resolutionChanged();
}
public void windowHidden()
{
super.windowHidden();
}
public void created()
{
bAlwaysOnTop = true;
super.created();
title = Plugin.i18n("mds.loadMaps.windowTitle");
clientWindow = create(new GWindowDialogClient()
{
public void resized()
{
super.resized();
Zuti_WMapsList.this.setSizes(this);
}
});
com.maddox.gwindow.GWindowDialogClient gwindowdialogclient = (com.maddox.gwindow.GWindowDialogClient)clientWindow;
lstMaps = new Table(gwindowdialogclient, Plugin.i18n("mds.loadMaps.listTitle"), 1.0F, 3.0F, 15.0F, 20.0F);
gwindowdialogclient.addControl(bLoadMap = new GWindowButton(gwindowdialogclient, 17.0F, 8.0F, 5.0F, 2.0F, (Plugin.i18n("mds.loadMaps.loadMap")), null)
{
public boolean notify(int i_61_, int i_62_)
{
if (i_61_ != 2)
return false;
loadMap();
return true;
}
});
}
private void setSizes(GWindow gwindow)
{
float win_X = gwindow.win.dx;
float win_Y = gwindow.win.dy;
lstMaps.setPosSize(5, 5, win_X - 10, win_Y - 40);
bLoadMap.setPosSize(5, win_Y - 25, win_X - 10, 20);
}
//----------------------------------------------------------------------
private void loadMap()
{
if( this.plMapLoad != null )
{
this.plMapLoad.zutiExecute( lstMaps.selectRow );
}
}
/**
* Close window.
*/
public void close(boolean flag)
{
super.close(flag);
}
/**
* Set window title
* @param newTitle
*/
public void setTitle(String newTitle)
{
title = Plugin.i18n("mds.loadMaps.windowTitle") + " - " + newTitle;
}
/**
* Clear maps list.
*/
public void clearMaps()
{
if( lstMaps.lst != null )
lstMaps.lst.clear();
}
/**
* Load all know maps into a list.
* @param lands
*/
public void loadMaps(ArrayList lands)
{
int size = lands.size();
for (int i = 0; i < size; i++)
{
Land land = (Land)lands.get(i);
this.lstMaps.lst.add(land.i18nName);
}
}
/**
* Set map loading plugin.
* @param mapLoad
*/
public void setPlMapLoad(PlMapLoad mapLoad)
{
this.plMapLoad = mapLoad;
}
}
You will note that most methods and properties of the obfuscated class (usually all private ones plus all genuine ones from MDS), including the classes' own name, are changed to a single letter of the alphabet (or two letter in case all single letters have been used already).
Furthermore multiple methods and properties are using the very same "name", here "letter".
For the binary java file this doesn't matter, but for humans it makes most of the code completely unreadable since you just don't know what's inside.
For instance the whole "builder" namespace of the obfuscated UP3 RC4 code contains obfuscated classes with names ranging from "a" to "zf" and they mostly look the same all over.
You just don't know what is what unless you get hands on the original code.
And that's even just the most basic level of obfuscation...
Hades used
Zelix KlassMaster for obfuscation but he only used the
Name Obfuscation feature of it.
Using more advanced features of obfuscation you can scramble the code even more until it becomes a total mess when being decompiled.
There's a nice survey of obfuscators from 2001 available here:
http://www.cs.auckland.ac.nz/~cthombor/Students/hlai/hongying.pdfNote that it's common sense that people using obfuscators on IL-2 are outlawed.
It's the worst style one can ever show: You pick what you get from the game itself (circumventing it's EULA which prohibits decompilation) and maybe even from the modding community, but the result you don't share back with the game's developers nor the community again, instead you protect it from being utilized and modified any further.
That's a disgusting attitude and no one should ever consider to use obfuscation in IL-2.
It's okay to obfuscate your very own code in commercial projects where you might have something worth to be protected from being stolen (and thereby negating your share of the commercial success of your project), but modding IL-2 isn't a commercial thing and everyone coding for IL-2 should be well aware that nothing of what he's doing here is done by himself alone, it would have never existed without the works of 1C/Maddox/TD/Other Community Members before.
Just don't do that. Don't use obfuscation. I did it myself once and it was the biggest mistake I ever made in IL-2. Trying vertical landings with a B-17 is a success story compared to that.
Best regards - Mike