0

我正在制作一个 minecraft mod,它是 Java 代码,我注意到一个奇怪的行为,其中一个 String 似乎正在丢失它的数据。我是 Java 新手,所以我对 Java 如何处理字符串或其他对象并不太了解。所以,我将说明我在做什么以及问题出在哪里:我有一个类,它有一些文本字段 ui 元素,用户可以输入这些元素来为项目命名。然后我所做的是每次用户更改字段中的文本时,它会将其内容的副本发送到另一个类,然后将它们发送到另一个类(由于我的世界的设置方式,这是必要的)然后当项目是创建后,最后一个类然后从它的自身中更新项目的名称。我不确定这是否是最好的方法,但这是我在短期内想到的。问题是,当创建项目时,最后一个类的名称字段(字符串)被擦除并且为空。我不确定为什么会发生这种情况或它是如何发生的,因为这些名称字段中的每一个仅在 ui 中的文本发生更改时才(重新)定义并且它们各自的类是私有的。所以,我很茫然。我将发布我的课程,希望你们能理解它们并帮助我。

GuiRecorder.java

package net.minecraft.src;

import org.lwjgl.opengl.GL11;

public class GuiRecorder extends GuiContainer
{
private TileEntityRecorder recorderInventory;
private GuiTextField discName;
private GuiTextField musicPath;
private ContainerRecorder record;
private boolean isInit;


public GuiRecorder(InventoryPlayer par1InventoryPlayer, TileEntityRecorder par2TileEntityRecorder)
{
    super(new ContainerRecorder(par1InventoryPlayer, par2TileEntityRecorder));
    this.recorderInventory = par2TileEntityRecorder;
    this.record = (ContainerRecorder)(this.inventorySlots);

    int var5 = (this.width - this.xSize) / 2;
    int var6 = (this.height - this.ySize) / 2;

    this.isInit = false;
}

/**
 * Capture Any/All key presses from the user and put them in the correct text field.
 */
protected void keyTyped(char par1, int par2)
{
    if (par2 == 1)
    {
        this.mc.thePlayer.closeScreen();
    }

    else if (this.discName.isFocused())
    {
        this.discName.textboxKeyTyped(par1, par2);
    }
    else if (this.musicPath.isFocused())
    {
        this.musicPath.textboxKeyTyped(par1, par2);
    }

    System.out.println("Keyboard hit! Code: " + par2);

    this.record.setName(this.discName.getText());
    this.record.setPath(this.musicPath.getText());
}

/**
 * Capture Any/All mouse clicks on the GUI.
 */
protected void mouseClicked(int par1, int par2, int par3)
{
    super.mouseClicked(par1, par2, par3);
    this.musicPath.mouseClicked(par1, par2, par3);
    this.discName.mouseClicked(par1, par2, par3);
}

public void onGuiClosed()
{
    this.record.setName(this.discName.getText());
    this.record.setPath(this.musicPath.getText());

    if (this.mc.thePlayer != null)
    {
        this.inventorySlots.onCraftGuiClosed(this.mc.thePlayer);
    }
}

/**
 * Draw the foreground layer for the GuiContainer (everything in front of the items)
 */
protected void drawGuiContainerForegroundLayer(int par1, int par2)
{
    this.fontRenderer.drawString(StatCollector.translateToLocal("container.inventory"), 8, this.ySize - 96 + 2, 4210752);
    this.fontRenderer.drawString("Disc Name:", (int)(this.xSize*0.02), (int)(this.ySize*0.03)+1, 4210752);
    this.fontRenderer.drawString("Music Path:", (int)(this.xSize*0.02), (int)(this.ySize*0.2)-1, 4210752);
}

/**
 * Draw the background layer for the GuiContainer (everything behind the items)
 */
protected void drawGuiContainerBackgroundLayer(float par1, int par2, int par3)
{       
    int var4 = this.mc.renderEngine.getTexture("/gui/recorder.png");
    GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
    this.mc.renderEngine.bindTexture(var4);
    int var5 = (this.width - this.xSize) / 2;
    int var6 = (this.height - this.ySize) / 2;
    this.drawTexturedModalRect(var5, var6, 0, 0, this.xSize, this.ySize);
    int var7;

    if(!this.isInit)
    {            
        this.discName = new GuiTextField(this.fontRenderer, var5 + 7, var6 + 16, 68, 10);
        this.musicPath = new GuiTextField(this.fontRenderer, var5 + 7, var6 + 39, 68, 10);

        this.discName.setFocused(true);
        this.musicPath.setFocused(false);

        this.discName.setText("Untitled");
        this.musicPath.setText("cat");

        this.isInit = true;
    }

    var7 = this.recorderInventory.getCookProgressScaled(24);
    this.drawTexturedModalRect(var5 + 111, var6 + 34, 176, 14, var7 + 1, 16);

    this.discName.drawTextBox();
    this.musicPath.drawTextBox();
}
} 

容器记录器.java

package net.minecraft.src;

import java.util.Iterator;

public class ContainerRecorder extends Container
{
private TileEntityRecorder recorder;
private int lastCookTime = 0;
private int lastBurnTime = 0;
private int lastItemBurnTime = 0;
public volatile String name;
public volatile String path;

public ContainerRecorder(InventoryPlayer par1InventoryPlayer, TileEntityRecorder par2TileEntityRecorder)
{
    this.recorder = par2TileEntityRecorder;
    this.addSlotToContainer(new Slot(par2TileEntityRecorder, 0, 87, 35));
    this.addSlotToContainer(new SlotRecorder(par1InventoryPlayer.player, par2TileEntityRecorder, 2, 148, 36));

    int var3;

    for (var3 = 0; var3 < 3; ++var3)
    {
        for (int var4 = 0; var4 < 9; ++var4)
        {
            this.addSlotToContainer(new Slot(par1InventoryPlayer, var4 + var3 * 9 + 9, 8 + var4 * 18, 84 + var3 * 18));
        }
    }

    for (var3 = 0; var3 < 9; ++var3)
    {
        this.addSlotToContainer(new Slot(par1InventoryPlayer, var3, 8 + var3 * 18, 142));
    }

    this.name = "Untitled";
    this.path = "cat";
}

public void addCraftingToCrafters(ICrafting par1ICrafting)
{
    super.addCraftingToCrafters(par1ICrafting);
    par1ICrafting.updateCraftingInventoryInfo(this, 0, this.recorder.currentBurnTime);
    par1ICrafting.updateCraftingInventoryInfo(this, 2, this.recorder.currentItemBurnTime);
}

/**
 * Updates crafting matrix; called from onCraftMatrixChanged. Args: none
 */
public void updateCraftingResults()
{
    super.updateCraftingResults();
    Iterator var1 = this.crafters.iterator();

    while (var1.hasNext())
    {
        ICrafting var2 = (ICrafting)var1.next();

        if (this.lastCookTime != this.recorder.currentBurnTime)
        {
            var2.updateCraftingInventoryInfo(this, 0, this.recorder.currentBurnTime);
        }

        if (this.lastItemBurnTime != this.recorder.currentItemBurnTime)
        {
            var2.updateCraftingInventoryInfo(this, 2, this.recorder.currentItemBurnTime);
        }
    }

    this.lastCookTime = this.recorder.currentBurnTime;
    this.lastBurnTime = this.recorder.burnTime;
    this.lastItemBurnTime = this.recorder.currentItemBurnTime;
}

public void updateProgressBar(int par1, int par2)
{
    if (par1 == 0)
    {
        this.recorder.currentBurnTime = par2;
    }

    if (par1 == 1)
    {
        this.recorder.burnTime = par2;
    }

    if (par1 == 2)
    {
        this.recorder.currentItemBurnTime = par2;
    }
}

public boolean canInteractWith(EntityPlayer par1EntityPlayer)
{
    return this.recorder.isUseableByPlayer(par1EntityPlayer);
}

public ItemStack func_82846_b(EntityPlayer par1EntityPlayer, int par2)
{
    ItemStack var3 = null;
    Slot var4 = (Slot)this.inventorySlots.get(par2);

    if (var4 != null && var4.getHasStack())
    {
        ItemStack var5 = var4.getStack();
        var3 = var5.copy();

        if (par2 == 2)
        {
            if (!this.mergeItemStack(var5, 3, 39, true))
            {
                return null;
            }

            var4.onSlotChange(var5, var3);
        }
        else if (par2 != 1 && par2 != 0)
        {
            if (RecorderRecipes.smelting().getSmeltingResult(var5.getItem().shiftedIndex) != null)
            {
                if (!this.mergeItemStack(var5, 0, 1, false))
                {
                    return null;
                }
            }
            else if (TileEntityRecorder.isItemFuel(var5))
            {
                if (!this.mergeItemStack(var5, 1, 2, false))
                {
                    return null;
                }
            }
            else if (par2 >= 3 && par2 < 30)
            {
                if (!this.mergeItemStack(var5, 30, 39, false))
                {
                    return null;
                }
            }
            else if (par2 >= 30 && par2 < 39 && !this.mergeItemStack(var5, 3, 30, false))
            {
                return null;
            }
        }
        else if (!this.mergeItemStack(var5, 3, 39, false))
        {
            return null;
        }

        if (var5.stackSize == 0)
        {
            var4.putStack((ItemStack)null);
        }
        else
        {
            var4.onSlotChanged();
        }

        if (var5.stackSize == var3.stackSize)
        {
            return null;
        }

        var4.func_82870_a(par1EntityPlayer, var5);
    }

    return var3;
}

public void setName(final String aName)
{
    this.name = aName;
    System.out.println("<ContainerRecorder>Record Name Set! Name: " + this.name);
    this.recorder.setDiscName(this.name);
    this.recorder.setMusicPath(this.path);
}

public void setPath(final String aPath)
{
    this.path = aPath;
    System.out.println("<ContainerRecorder>Record Path Set! Path: " + this.path);
    this.recorder.setDiscName(this.name);
    this.recorder.setMusicPath(this.path);
}
}

TileEntityRecorderer.java

package net.minecraft.src;

public class TileEntityRecorder extends TileEntity implements IInventory
{
/**
 * The ItemStacks that hold the items currently being used in the recorder
 */
private ItemStack[] recorderItemStacks = new ItemStack[3];

/** The number of ticks that the recorder will keep burning */
public int burnTime = 0;

/**
 * The number of ticks that a fresh copy of the currently-burning item would keep the recorder burning for
 */
public int currentItemBurnTime = 0;

/** The number of ticks that the current item has been cooking for */
public int currentBurnTime = 0;

protected String name;
protected String path;

/**
 * Returns the number of slots in the inventory.
 */
public int getSizeInventory()
{
    return this.recorderItemStacks.length;
}

/**
 * Returns the stack in slot i
 */
public ItemStack getStackInSlot(int par1)
{
    return this.recorderItemStacks[par1];
}

/**
 * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a
 * new stack.
 */
public ItemStack decrStackSize(int par1, int par2)
{
    if (this.recorderItemStacks[par1] != null)
    {
        ItemStack var3;

        if (this.recorderItemStacks[par1].stackSize <= par2)
        {
            var3 = this.recorderItemStacks[par1];
            this.recorderItemStacks[par1] = null;
            return var3;
        }
        else
        {
            var3 = this.recorderItemStacks[par1].splitStack(par2);

            if (this.recorderItemStacks[par1].stackSize == 0)
            {
                this.recorderItemStacks[par1] = null;
            }

            return var3;
        }
    }
    else
    {
        return null;
    }
}

/**
 * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem -
 * like when you close a workbench GUI.
 */
public ItemStack getStackInSlotOnClosing(int par1)
{
    if (this.recorderItemStacks[par1] != null)
    {
        ItemStack var2 = this.recorderItemStacks[par1];
        this.recorderItemStacks[par1] = null;
        return var2;
    }
    else
    {
        return null;
    }
}

/**
 * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections).
 */
public void setInventorySlotContents(int par1, ItemStack par2ItemStack)
{
    this.recorderItemStacks[par1] = par2ItemStack;

    if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit())
    {
        par2ItemStack.stackSize = this.getInventoryStackLimit();
    }
}

/**
 * Returns the name of the inventory.
 */
public String getInvName()
{
    return "container.recorder";
}

/**
 * Reads a tile entity from NBT.
 */
public void readFromNBT(NBTTagCompound par1NBTTagCompound)
{
    super.readFromNBT(par1NBTTagCompound);
    NBTTagList var2 = par1NBTTagCompound.getTagList("Items");
    this.recorderItemStacks = new ItemStack[this.getSizeInventory()];

    for (int var3 = 0; var3 < var2.tagCount(); ++var3)
    {
        NBTTagCompound var4 = (NBTTagCompound)var2.tagAt(var3);
        byte var5 = var4.getByte("Slot");

        if (var5 >= 0 && var5 < this.recorderItemStacks.length)
        {
            this.recorderItemStacks[var5] = ItemStack.loadItemStackFromNBT(var4);
        }
    }

    this.name = par1NBTTagCompound.getString("Name");
    this.path = par1NBTTagCompound.getString("Path");
    this.burnTime = par1NBTTagCompound.getShort("BurnTime");
    this.currentBurnTime = par1NBTTagCompound.getShort("CurrentBurnTime");
    this.currentItemBurnTime = getItemBurnTime(this.recorderItemStacks[1]);
}

/**
 * Writes a tile entity to NBT.
 */
public void writeToNBT(NBTTagCompound par1NBTTagCompound)
{
    super.writeToNBT(par1NBTTagCompound);
    par1NBTTagCompound.setShort("BurnTime", (short)this.burnTime);
    par1NBTTagCompound.setShort("CurrentBurnTime", (short)this.currentBurnTime);
    par1NBTTagCompound.setString("Name", this.name);
    par1NBTTagCompound.setString("Path", this.path);
    NBTTagList var2 = new NBTTagList();

    for (int var3 = 0; var3 < this.recorderItemStacks.length; ++var3)
    {
        if (this.recorderItemStacks[var3] != null)
        {
            NBTTagCompound var4 = new NBTTagCompound();
            var4.setByte("Slot", (byte)var3);
            this.recorderItemStacks[var3].writeToNBT(var4);
            var2.appendTag(var4);
        }
    }

    par1NBTTagCompound.setTag("Items", var2);
}

/**
 * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't
 * this more of a set than a get?*
 */
public int getInventoryStackLimit()
{
    return 64;
}

/**
 * Returns an integer between 0 and the passed value representing how close the current item is to being completely
 * cooked
 */
public int getCookProgressScaled(int par1)
{
    return this.currentBurnTime * par1 / 200;
}

/**
 * Returns an integer between 0 and the passed value representing how much burn time is left on the current fuel
 * item, where 0 means that the item is exhausted and the passed value means that the item is fresh
 */
public int getBurnTimeRemainingScaled(int par1)
{
    if (this.currentItemBurnTime == 0)
    {
        this.currentItemBurnTime = 200;
    }

    return this.burnTime * par1 / this.currentItemBurnTime;
}

/**
 * Returns true if the recorder is currently burning
 */
public boolean isBurning()
{
    return this.burnTime > 0;
}

/**
 * Allows the entity to update its state. Overridden in most subclasses, e.g. the mob spawner uses this to count
 * ticks and creates a new spawn inside its implementation.
 */
public void updateEntity()
{
    boolean var1 = this.burnTime > 0;
    boolean var2 = false;

    if (this.burnTime > 0)
    {
        --this.burnTime;
    }

    if (!this.worldObj.isRemote)
    {
        if (this.burnTime == 0 && this.canSmelt())
        {
            this.currentItemBurnTime = this.burnTime = getItemBurnTime(this.recorderItemStacks[1]);

            if (this.burnTime > 0)
            {
                var2 = true;

                if (this.recorderItemStacks[1] != null)
                {
                    --this.recorderItemStacks[1].stackSize;

                    if (this.recorderItemStacks[1].stackSize == 0)
                    {
                        Item var3 = this.recorderItemStacks[1].getItem().getContainerItem();
                        this.recorderItemStacks[1] = var3 != null ? new ItemStack(var3) : null;
                    }
                }
            }
        }

        if (this.isBurning() && this.canSmelt())
        {
            ++this.currentBurnTime;

            if (this.currentBurnTime == 200)
            {
                this.currentBurnTime = 0;
                this.smeltItem();
                var2 = true;
            }
        }
        else
        {
            this.currentBurnTime = 0;
        }
    }

    if (var2)
    {
        this.onInventoryChanged();
    }
}

/**
 * Returns true if the recorder can smelt an item, i.e. has a source item, destination stack isn't full, etc.
 */
private boolean canSmelt()
{
    if (this.recorderItemStacks[0] == null)
    {
        return false;
    }
    else
    {
        ItemStack var1 = RecorderRecipes.smelting().getSmeltingResult(this.recorderItemStacks[0].getItem().shiftedIndex);
        return var1 == null ? false : (this.recorderItemStacks[2] == null ? true : (!this.recorderItemStacks[2].isItemEqual(var1) ? false : (this.recorderItemStacks[2].stackSize < this.getInventoryStackLimit() && this.recorderItemStacks[2].stackSize < this.recorderItemStacks[2].getMaxStackSize() ? true : this.recorderItemStacks[2].stackSize < var1.getMaxStackSize())));
    }
}

/**
 * Turn one item from the recorder source stack into the appropriate smelted item in the recorder result stack
 */
public void smeltItem()
{       
    if (this.canSmelt())
    {
        ItemStack var1 = RecorderRecipes.smelting().getSmeltingResult(this.recorderItemStacks[0].getItem().shiftedIndex);

        if (this.recorderItemStacks[2] == null)
        {
            this.recorderItemStacks[2] = var1.copy();
        }
        else if (this.recorderItemStacks[2].itemID == var1.itemID)
        {
            ++this.recorderItemStacks[2].stackSize;
        }

        --this.recorderItemStacks[0].stackSize;

        if (this.recorderItemStacks[0].stackSize <= 0)
        {
            this.recorderItemStacks[0] = null;
        }

        System.out.println("<TileEntityRecorder>(smeltItem) Name: "+this.name);
        System.out.println("<TileEntityRecorder>(smeltItem) Path: "+this.path);
        ItemCustomRecord custom = (ItemCustomRecord)(var1.getItem());
        custom.SetName(this.name);
        custom.SetPath(this.path);
    }
}

/**
 * Returns the number of ticks that the supplied fuel item will keep the recorder burning, or 0 if the item isn't
 * fuel
 */
public static int getItemBurnTime(ItemStack par0ItemStack)
{
   return 250;
}

/**
 * Return true if item is a fuel source (getItemBurnTime() > 0).
 */
public static boolean isItemFuel(ItemStack par0ItemStack)
{       
    return getItemBurnTime(par0ItemStack) > 0;
}

/**
 * Do not make give this method the name canInteractWith because it clashes with Container
 */
public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
{
    return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false : par1EntityPlayer.getDistanceSq((double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D) <= 64.0D;
}

public void openChest() {}

public void closeChest() {}

public void setDiscName(final String aName)
{
    this.name = aName;
    System.out.println("<TileEntityRecorder>Record Name Set! Name: " + this.name);
}

public void setMusicPath(final String aName)
{
    this.path = aName;
    System.out.println("<TileEntityRecorder>Record Path Set! Path: " + this.path);
}
}

ItemCustomRecord.java

package net.minecraft.src;

import java.util.List;

public class ItemCustomRecord extends Item
{
/** The name of the record. */
public volatile String recordName;
public volatile String musicName;

protected ItemCustomRecord(int par1)
{
    super(par1);
    this.maxStackSize = 1;
    this.setCreativeTab(CreativeTabs.tabMisc);
    this.recordName= "Untitled";
    this.musicName = "cat";
}

public void SetName(final String par1)
{
    this.recordName = par1;
    System.out.println("<ItemCustomRecord>Name Set! Name: "+this.recordName);
}

public void SetPath(final String par1)
{
    this.musicName = par1;
    System.out.println("<ItemCustomRecord>Path Set! Path: "+this.musicName);
}

/**
 * Callback for item usage. If the item does something special on right clicking, he will have one of those. Return
 * True if something happen and false if it don't. This is for ITEMS, not BLOCKS
 */
public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10)
{
    if (par3World.getBlockId(par4, par5, par6) == Block.jukebox.blockID && par3World.getBlockMetadata(par4, par5, par6) == 0)
    {
        if (par3World.isRemote)
        {
            return true;
        }
        else
        {
            ((BlockJukeBox)Block.jukebox).insertRecord(par3World, par4, par5, par6, this.shiftedIndex);
            par3World.playAuxSFXAtEntity((EntityPlayer)null, 1006, par4, par5, par6, this.shiftedIndex);
            --par1ItemStack.stackSize;
            return true;
        }
    }
    else
    {
        return false;
    }
}

/**
 * allows items to add custom lines of information to the mouseover description
 */
public void addInformation(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, List par3List, boolean par4)
{
    par3List.add("Custom - " + this.recordName);
}

/**
 * Return an item rarity from EnumRarity
 */
public EnumRarity getRarity(ItemStack par1ItemStack)
{
    return EnumRarity.epic;
}
}

我希望你们能帮助我,因为这真的减慢了我的模组速度……嗯,它实际上突然停止了。非常感谢所有帮助!

4

1 回答 1

1

字符串是不可变的对象,创建后不能更改。

于 2012-11-10T04:26:46.760 回答