- 1,990
- 18
- 109
Закину сюда деобфусцированный ручками класс GuiContainer.
Просто решил поделиться человеческим кодом.
Может иногда буду кидать ещё различные расшифрованные классы из ванильки.
Вот: http://pastebin.com/gxvuqdrL
Заодно закину клон сюда, вдруг пастебин удалит:
P.S. Деобфусцированный - приведенный в нормальный вид, т.е. без полей уровня field_ahalaymahalay.
Просто решил поделиться человеческим кодом.
Может иногда буду кидать ещё различные расшифрованные классы из ванильки.
Вот: http://pastebin.com/gxvuqdrL
Заодно закину клон сюда, вдруг пастебин удалит:
Код:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import com.mojang.realmsclient.gui.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IIcon;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ResourceLocation;
public abstract class GuiContainerImpl extends GuiContainer {
protected static final ResourceLocation texture = new ResourceLocation("textures/gui/container/inventory.png");
/** The X size of the inventory window in pixels. */
protected int xSize = 176;
/** The Y size of the inventory window in pixels. */
protected int ySize = 166;
/** A list of the players inventory slots */
public Container inventorySlots;
/** Starting X position for the Gui. Inconsistent use for Gui backgrounds. */
protected int guiLeft;
/** Starting Y position for the Gui. Inconsistent use for Gui backgrounds. */
protected int guiTop;
protected Slot theSlot;
/** Used when touchscreen is enabled. */
protected Slot selectedSlot;
/** Used when touchscreen is enabled. */
protected boolean isRightMouseClick;
/** Used when touchscreen is enabled */
protected ItemStack draggedStack;
protected Slot returningStackDestSlot;
protected long returningStackTime;
/** some touchscreen x/y variables */
protected int touchX;
protected int touchY;
/** A set of itemstacks being placed into multiple slots while dragging */
protected final Set placedItemstacks = new HashSet();
/** Used when touchscreen is enabled */
protected ItemStack returningStack;
/** Some itemstack referred to shiftclicking */
protected ItemStack shiftItemstack;
/** some touchscreen slot, seems to be the destination slot item is being moved to */
protected Slot touchDestSlot;
protected Slot lastClickedSlot;
protected boolean isDragging;
protected boolean ignoreNextReleaseEvent;
protected boolean doubleClick;
/** some touchscreen time-value, no need in this */
protected long lastTouchTime;
protected long lastClickTime;
protected int draggedButton;
/** The last released button while holding an itemstack */
protected int lastReleasedButton;
/** Stacksize of the item current being divided (when item is being dragged around the inventory) */
protected int dividedItemStacksize;
protected int lastClickedButton;
public GuiContainerImpl(Container container)
{
super(null);
this.inventorySlots = container;
this.ignoreNextReleaseEvent = true;
}
/**
* Adds the buttons (and other controls) to the screen in question.
*/
public void initGui()
{
this.mc.thePlayer.openContainer = this.inventorySlots;
this.guiLeft = (this.width - this.xSize) / 2;
this.guiTop = (this.height - this.ySize) / 2;
}
/**
* Draws the screen and all the components in it.
*/
public void drawScreen(int mx, int my, float partialTicks)
{
this.drawDefaultBackground();
int left = this.guiLeft;
int top = this.guiTop;
this.drawGuiContainerBackgroundLayer(partialTicks, mx, my);
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
RenderHelper.disableStandardItemLighting();
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_DEPTH_TEST);
RenderHelper.enableGUIStandardItemLighting();
GL11.glPushMatrix();
GL11.glTranslatef((float)left, (float)top, 0.0F);
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
this.theSlot = null;
short u = 240;
short v = 240;
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)u / 1.0F, (float)v / 1.0F);
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
int slotY;
for (int i1 = 0; i1 < this.inventorySlots.inventorySlots.size(); ++i1)
{
Slot slot = (Slot)this.inventorySlots.inventorySlots.get(i1);
this.renderSlot(slot);
if (this.isMouseOverSlot(slot, mx, my) && slot.func_111238_b())
{
this.theSlot = slot;
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_DEPTH_TEST);
int slotX = slot.xDisplayPosition;
slotY = slot.yDisplayPosition;
GL11.glColorMask(true, true, true, false);
this.drawGradientRect(slotX, slotY, slotX + 16, slotY + 16, -2130706433, -2130706433);
GL11.glColorMask(true, true, true, true);
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_DEPTH_TEST);
}
}
//Forge: Force lighting to be disabled as there are some issue where lighting would
//incorrectly be applied based on items that are in the inventory.
GL11.glDisable(GL11.GL_LIGHTING);
this.drawGuiContainerForegroundLayer(mx, my);
GL11.glEnable(GL11.GL_LIGHTING);
InventoryPlayer inventoryplayer = this.mc.thePlayer.inventory;
ItemStack itemstack = this.draggedStack == null ? inventoryplayer.getItemStack() : this.draggedStack;
if (itemstack != null)
{
slotY = this.draggedStack == null ? 8 : 16;
String s = null;
if (this.draggedStack != null && this.isRightMouseClick)
{
itemstack = itemstack.copy();
itemstack.stackSize = MathHelper.ceiling_float_int((float)itemstack.stackSize / 2.0F);
}
else if (this.isDragging && this.placedItemstacks.size() > 1)
{
itemstack = itemstack.copy();
itemstack.stackSize = this.dividedItemStacksize;
if (itemstack.stackSize == 0)
{
s = "" + EnumChatFormatting.YELLOW + "0";
}
}
this.drawItemStack(itemstack, mx - left - 8, my - top - slotY, s);
}
if (this.returningStack != null)
{
float f1 = (float)(Minecraft.getSystemTime() - this.returningStackTime) / 100.0F;
if (f1 >= 1.0F)
{
f1 = 1.0F;
this.returningStack = null;
}
slotY = this.returningStackDestSlot.xDisplayPosition - this.touchX;
int j2 = this.returningStackDestSlot.yDisplayPosition - this.touchY;
int l1 = this.touchX + (int)((float)slotY * f1);
int i2 = this.touchY + (int)((float)j2 * f1);
this.drawItemStack(this.returningStack, l1, i2, (String)null);
}
GL11.glPopMatrix();
if (inventoryplayer.getItemStack() == null && this.theSlot != null && this.theSlot.getHasStack())
{
ItemStack itemstack1 = this.theSlot.getStack();
this.renderToolTip(itemstack1, mx, my);
}
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_DEPTH_TEST);
RenderHelper.enableStandardItemLighting();
}
protected void drawItemStack(ItemStack itemstack, int x, int y, String strCount)
{
GL11.glTranslatef(0.0F, 0.0F, 32.0F);
this.zLevel = 200.0F;
itemRender.zLevel = 200.0F;
FontRenderer font = null;
if (itemstack != null) font = itemstack.getItem().getFontRenderer(itemstack);
if (font == null) font = fontRendererObj;
itemRender.renderItemAndEffectIntoGUI(font, this.mc.getTextureManager(), itemstack, x, y);
itemRender.renderItemOverlayIntoGUI(font, this.mc.getTextureManager(), itemstack, x, y - (this.draggedStack == null ? 0 : 8), strCount);
this.zLevel = 0.0F;
itemRender.zLevel = 0.0F;
}
/**
* Draw the foreground layer for the GuiContainer (everything in front of the items)
*/
protected void drawGuiContainerForegroundLayer(int x, int y) {}
protected abstract void drawGuiContainerBackgroundLayer(float partialTicks, int x, int y);
protected void renderSlot(Slot slot)
{
int x = slot.xDisplayPosition;
int y = slot.yDisplayPosition;
ItemStack itemstack = slot.getStack();
boolean isHighlighted = false;
boolean cancelItemRender = slot == this.selectedSlot && this.draggedStack != null && !this.isRightMouseClick;
ItemStack heldItemstack = this.mc.thePlayer.inventory.getItemStack();
String itemCount = null;
if (slot == this.selectedSlot && this.draggedStack != null && this.isRightMouseClick && itemstack != null)
{
itemstack = itemstack.copy();
itemstack.stackSize /= 2;
}
else if (this.isDragging && this.placedItemstacks.contains(slot) && heldItemstack != null)
{
if (this.placedItemstacks.size() == 1)
{
return;
}
if (Container.func_94527_a(slot, heldItemstack, true) && this.inventorySlots.canDragIntoSlot(slot))
{
itemstack = heldItemstack.copy();
isHighlighted = true;
Container.func_94525_a(this.placedItemstacks, this.draggedButton, itemstack, slot.getStack() == null ? 0 : slot.getStack().stackSize);
if (itemstack.stackSize > itemstack.getMaxStackSize())
{
itemCount = EnumChatFormatting.YELLOW + "" + itemstack.getMaxStackSize();
itemstack.stackSize = itemstack.getMaxStackSize();
}
if (itemstack.stackSize > slot.getSlotStackLimit())
{
itemCount = EnumChatFormatting.YELLOW + "" + slot.getSlotStackLimit();
itemstack.stackSize = slot.getSlotStackLimit();
}
}
else
{
this.placedItemstacks.remove(slot);
this.divideItemstacks();
}
}
this.zLevel = 100.0F;
itemRender.zLevel = 100.0F;
if (itemstack == null)
{
IIcon iicon = slot.getBackgroundIconIndex();
if (iicon != null)
{
GL11.glDisable(GL11.GL_LIGHTING);
this.mc.getTextureManager().bindTexture(TextureMap.locationItemsTexture);
this.drawTexturedModelRectFromIcon(x, y, iicon, 16, 16);
GL11.glEnable(GL11.GL_LIGHTING);
cancelItemRender = true;
}
}
if (!cancelItemRender)
{
if (isHighlighted)
{
drawRect(x, y, x + 16, y + 16, -2130706433);
}
GL11.glEnable(GL11.GL_DEPTH_TEST);
itemRender.renderItemAndEffectIntoGUI(this.fontRendererObj, this.mc.getTextureManager(), itemstack, x, y);
itemRender.renderItemOverlayIntoGUI(this.fontRendererObj, this.mc.getTextureManager(), itemstack, x, y, itemCount);
}
itemRender.zLevel = 0.0F;
this.zLevel = 0.0F;
}
/** Method is called while dragging mouse around the empty slots with a not null held item */
protected void divideItemstacks()
{
ItemStack itemstack = this.mc.thePlayer.inventory.getItemStack();
if (itemstack != null && this.isDragging)
{
this.dividedItemStacksize = itemstack.stackSize;
ItemStack itemstack1;
int i;
for (Iterator iterator = this.placedItemstacks.iterator(); iterator.hasNext(); this.dividedItemStacksize -= itemstack1.stackSize - i)
{
Slot slot = (Slot)iterator.next();
itemstack1 = itemstack.copy();
i = slot.getStack() == null ? 0 : slot.getStack().stackSize;
Container.func_94525_a(this.placedItemstacks, this.draggedButton, itemstack1, i);
if (itemstack1.stackSize > itemstack1.getMaxStackSize())
{
itemstack1.stackSize = itemstack1.getMaxStackSize();
}
if (itemstack1.stackSize > slot.getSlotStackLimit())
{
itemstack1.stackSize = slot.getSlotStackLimit();
}
}
}
}
/**
* Returns the slot at the given coordinates or null if there is none.
*/
protected Slot getSlotAtPosition(int x, int y)
{
for (int k = 0; k < this.inventorySlots.inventorySlots.size(); ++k)
{
Slot slot = (Slot)this.inventorySlots.inventorySlots.get(k);
if (this.isMouseOverSlot(slot, x, y))
{
return slot;
}
}
return null;
}
/**
* Called when the mouse is clicked.
*/
protected void mouseClicked(int mx, int my, int mouseButton)
{
boolean flag = mouseButton == this.mc.gameSettings.keyBindPickBlock.getKeyCode() + 100;
Slot handledSlot = this.getSlotAtPosition(mx, my);
long time = Minecraft.getSystemTime();
this.doubleClick = this.lastClickedSlot == handledSlot && time - this.lastClickTime < 250L && this.lastClickedButton == mouseButton;
this.ignoreNextReleaseEvent = false;
if (mouseButton == 0 || mouseButton == 1 || flag)
{
int x = this.guiLeft;
int y = this.guiTop;
boolean outsideBounds = mx < x || my < y || mx >= x + this.xSize || my >= y + this.ySize;
int slotIndex = -1;
if (handledSlot != null)
{
slotIndex = handledSlot.slotNumber;
}
//mark item to drop
if (outsideBounds)
{
slotIndex = -999;
}
//exits the menu if tapped outside of the window bounds [touchscreen]
if (this.mc.gameSettings.touchscreen && outsideBounds && this.mc.thePlayer.inventory.getItemStack() == null)
{
this.mc.displayGuiScreen((GuiScreen)null);
return;
}
if (slotIndex != -1)
{
if (this.mc.gameSettings.touchscreen)
{
if (handledSlot != null && handledSlot.getHasStack())
{
this.selectedSlot = handledSlot;
this.draggedStack = null;
this.isRightMouseClick = mouseButton == 1;
}
else
{
this.selectedSlot = null;
}
}
else if (!this.isDragging)
{
if (this.mc.thePlayer.inventory.getItemStack() == null)
{
if (mouseButton == this.mc.gameSettings.keyBindPickBlock.getKeyCode() + 100)
{
this.handleMouseClick(handledSlot, slotIndex, mouseButton, 3);
}
else
{
boolean shiftPressed = slotIndex != -999 && (Keyboard.isKeyDown(42) || Keyboard.isKeyDown(54));
byte action = 0; //take item
if (shiftPressed)
{
this.shiftItemstack = handledSlot != null && handledSlot.getHasStack() ? handledSlot.getStack() : null;
action = 1;
}
else if (slotIndex == -999)
{
action = 4; //drop item
}
this.handleMouseClick(handledSlot, slotIndex, mouseButton, action);
}
this.ignoreNextReleaseEvent = true;
}
else
{
this.isDragging = true;
this.lastReleasedButton = mouseButton;
this.placedItemstacks.clear();
if (mouseButton == 0)
{
this.draggedButton = 0;
}
else if (mouseButton == 1)
{
this.draggedButton = 1;
}
}
}
}
}
this.lastClickedSlot = handledSlot;
this.lastClickTime = time;
this.lastClickedButton = mouseButton;
}
/**
* Called when a mouse button is pressed and the mouse is moved around. Parameters are : mouseX, mouseY,
* lastButtonClicked & timeSinceMouseClick.
*/
protected void mouseClickMove(int mx, int my, int lastButtonClicked, long timeSinceMouseClick)
{
Slot slot = this.getSlotAtPosition(mx, my);
ItemStack heldItemstack = this.mc.thePlayer.inventory.getItemStack();
if (this.selectedSlot != null && this.mc.gameSettings.touchscreen)
{
if (lastButtonClicked == 0 || lastButtonClicked == 1)
{
if (this.draggedStack == null)
{
if (slot != this.selectedSlot)
{
this.draggedStack = this.selectedSlot.getStack().copy();
}
}
else if (this.draggedStack.stackSize > 1 && slot != null && Container.func_94527_a(slot, this.draggedStack, false))
{
long i1 = Minecraft.getSystemTime();
if (this.touchDestSlot == slot)
{
if (i1 - this.lastTouchTime > 500L)
{
this.handleMouseClick(this.selectedSlot, this.selectedSlot.slotNumber, 0, 0);
this.handleMouseClick(slot, slot.slotNumber, 1, 0);
this.handleMouseClick(this.selectedSlot, this.selectedSlot.slotNumber, 0, 0);
this.lastTouchTime = i1 + 750L;
--this.draggedStack.stackSize;
}
}
else
{
this.touchDestSlot = slot;
this.lastTouchTime = i1;
}
}
}
}
else if (this.isDragging && slot != null && heldItemstack != null && heldItemstack.stackSize > this.placedItemstacks.size() && Container.func_94527_a(slot, heldItemstack, true) && slot.isItemValid(heldItemstack) && this.inventorySlots.canDragIntoSlot(slot))
{
this.placedItemstacks.add(slot);
this.divideItemstacks();
}
}
/**
* Called when the mouse is moved or a mouse button is released. Signature: (mouseX, mouseY, which) which==-1 is
* mouseMove, which==0 or which==1 is mouseUp
*/
protected void mouseMovedOrUp(int mx, int my, int mouseButton)
{
Slot slot = this.getSlotAtPosition(mx, my);
int left = this.guiLeft;
int top = this.guiTop;
boolean outsideBounds = mx < left || my < top || mx >= left + this.xSize || my >= top + this.ySize;
int slotIndex = -1;
if (slot != null)
{
slotIndex = slot.slotNumber;
}
if (outsideBounds)
{
slotIndex = -999;
}
Slot slot1;
Iterator iterator;
if (this.doubleClick && slot != null && mouseButton == 0 && this.inventorySlots.func_94530_a((ItemStack)null, slot))
{
if (isShiftKeyDown())
{
if (slot != null && slot.inventory != null && this.shiftItemstack != null)
{
iterator = this.inventorySlots.inventorySlots.iterator();
while (iterator.hasNext())
{
slot1 = (Slot)iterator.next();
if (slot1 != null && slot1.canTakeStack(this.mc.thePlayer) && slot1.getHasStack() && slot1.inventory == slot.inventory && Container.func_94527_a(slot1, this.shiftItemstack, true))
{
this.handleMouseClick(slot1, slot1.slotNumber, mouseButton, 1);
}
}
}
}
else
{
//performs double click: collects as many items as it can
//from all over the inventory into a held item
this.handleMouseClick(slot, slotIndex, mouseButton, 6);
}
this.doubleClick = false;
this.lastClickTime = 0L;
}
else
{
if (this.isDragging && this.lastReleasedButton != mouseButton)
{
this.isDragging = false;
this.placedItemstacks.clear();
this.ignoreNextReleaseEvent = true;
return;
}
if (this.ignoreNextReleaseEvent)
{
this.ignoreNextReleaseEvent = false;
return;
}
boolean shiftPressed;
//ignoring this section, nah need in this
if (this.selectedSlot != null && this.mc.gameSettings.touchscreen)
{
if (mouseButton == 0 || mouseButton == 1)
{
if (this.draggedStack == null && slot != this.selectedSlot)
{
this.draggedStack = this.selectedSlot.getStack();
}
shiftPressed = Container.func_94527_a(slot, this.draggedStack, false);
if (slotIndex != -1 && this.draggedStack != null && shiftPressed)
{
this.handleMouseClick(this.selectedSlot, this.selectedSlot.slotNumber, mouseButton, 0);
this.handleMouseClick(slot, slotIndex, 0, 0);
if (this.mc.thePlayer.inventory.getItemStack() != null)
{
this.handleMouseClick(this.selectedSlot, this.selectedSlot.slotNumber, mouseButton, 0);
this.touchX = mx - left;
this.touchY = my - top;
this.returningStackDestSlot = this.selectedSlot;
this.returningStack = this.draggedStack;
this.returningStackTime = Minecraft.getSystemTime();
}
else
{
this.returningStack = null;
}
}
else if (this.draggedStack != null)
{
this.touchX = mx - left;
this.touchY = my - top;
this.returningStackDestSlot = this.selectedSlot;
this.returningStack = this.draggedStack;
this.returningStackTime = Minecraft.getSystemTime();
}
this.draggedStack = null;
this.selectedSlot = null;
}
}
else if (isDragging && !this.placedItemstacks.isEmpty())
{
this.handleMouseClick((Slot)null, -999, Container.func_94534_d(0, this.draggedButton), 5);
iterator = this.placedItemstacks.iterator();
while (iterator.hasNext())
{
slot1 = (Slot)iterator.next();
this.handleMouseClick(slot1, slot1.slotNumber, Container.func_94534_d(1, this.draggedButton), 5);
}
this.handleMouseClick((Slot)null, -999, Container.func_94534_d(2, this.draggedButton), 5);
}
else if (this.mc.thePlayer.inventory.getItemStack() != null)
{
if (mouseButton == this.mc.gameSettings.keyBindPickBlock.getKeyCode() + 100)
{
this.handleMouseClick(slot, slotIndex, mouseButton, 3);
}
else
{
shiftPressed = slotIndex != -999 && (Keyboard.isKeyDown(42) || Keyboard.isKeyDown(54));
if (shiftPressed)
{
this.shiftItemstack = slot != null && slot.getHasStack() ? slot.getStack() : null;
}
this.handleMouseClick(slot, slotIndex, mouseButton, shiftPressed ? 1 : 0);
}
}
}
if (this.mc.thePlayer.inventory.getItemStack() == null)
{
this.lastClickTime = 0L;
}
this.isDragging = false;
}
/**
* Returns if the passed mouse position is over the specified slot.
*/
protected boolean isMouseOverSlot(Slot slot, int mx, int my)
{
return this.isPointInRegion(slot.xDisplayPosition, slot.yDisplayPosition, 16, 16, mx, my);
}
protected boolean isPointInRegion(int left, int top, int width, int height, int pointX, int pointY)
{
int k1 = this.guiLeft;
int l1 = this.guiTop;
pointX -= k1;
pointY -= l1;
return pointX >= left - 1 && pointX < left + width + 1 && pointY >= top - 1 && pointY < top + height + 1;
}
protected void handleMouseClick(Slot slot, int slotIndex, int mouseButton, int par4)
{
if (slot != null)
{
slotIndex = slot.slotNumber;
}
this.mc.playerController.windowClick(this.inventorySlots.windowId, slotIndex, mouseButton, par4, this.mc.thePlayer);
}
/**
* Fired when a key is typed. This is the equivalent of KeyListener.keyTyped(KeyEvent e).
*/
protected void keyTyped(char keyChar, int keyCode)
{
this.checkHotbarKeys(keyCode);
if (this.theSlot != null && this.theSlot.getHasStack())
{
if (keyCode == this.mc.gameSettings.keyBindPickBlock.getKeyCode())
{
this.handleMouseClick(this.theSlot, this.theSlot.slotNumber, 0, 3);
}
else if (keyCode == this.mc.gameSettings.keyBindDrop.getKeyCode())
{
this.handleMouseClick(this.theSlot, this.theSlot.slotNumber, isCtrlKeyDown() ? 1 : 0, 4);
}
}
}
/**
* This function is what controls the hotbar shortcut check when you press a number key when hovering a stack.
*/
protected boolean checkHotbarKeys(int pressedNumber)
{
if (this.mc.thePlayer.inventory.getItemStack() == null && this.theSlot != null)
{
for (int j = 0; j < 9; ++j)
{
if (pressedNumber == this.mc.gameSettings.keyBindsHotbar[j].getKeyCode())
{
this.handleMouseClick(this.theSlot, this.theSlot.slotNumber, j, 2);
return true;
}
}
}
return false;
}
/**
* Called when the screen is unloaded. Used to disable keyboard repeat events
*/
public void onGuiClosed()
{
if (this.mc.thePlayer != null)
{
this.inventorySlots.onContainerClosed(this.mc.thePlayer);
}
}
/**
* Returns true if this GUI should pause the game when it is displayed in single-player
*/
public boolean doesGuiPauseGame()
{
return false;
}
/**
* Called from the main game loop to update the screen.
*/
public void updateScreen()
{
if (!this.mc.thePlayer.isEntityAlive() || this.mc.thePlayer.isDead)
{
this.mc.thePlayer.closeScreen();
}
}
}
P.S. Деобфусцированный - приведенный в нормальный вид, т.е. без полей уровня field_ahalaymahalay.