我正在制作一个 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;
}
}
我希望你们能帮助我,因为这真的减慢了我的模组速度……嗯,它实际上突然停止了。非常感谢所有帮助!