- 128
- 4
- 6
Я создал блок, с возможностью в нем создавать разнообразные рецепты, данный блок похож на наковальню и блок из новых версий майна кузнечный стол.
Одна проблема которую я ни как не могу решить хотя ответ где-то рядом, не знаю в каком направлении думать. Нужно добавить возможность переименовки предметов, однако столкнулся с непонятным решением в ваниле.
Уже много вариантов перебрал но, переименовка не работает. Подскажите как правильно это все реализовать.
Одна проблема которую я ни как не могу решить хотя ответ где-то рядом, не знаю в каком направлении думать. Нужно добавить возможность переименовки предметов, однако столкнулся с непонятным решением в ваниле.
Tile:
public class SmithingAlchemyTableTile extends TileInventoryBasic implements ITickable {
public static final int INV_SIZE = 5;
public static final String nameInv = "container.brazier_soul";
private int lvlFire = -1;
private boolean clientSideUpdate = false;
private String customName = "";
public SmithingAlchemyTableTile() { super(nameInv, INV_SIZE, 64); }
@Override public void update() {
if (world.isRemote) {
clientSideUpdate = true;
markDirty();
return;
}
setFireToBrazierSoul();
boolean foundRecipe = false;
ItemStack catalystSlot = getStackInSlot(SmithingAlchemyTableContainer.CATALYST_SLOT);
for (SmithingAlchemyTableRecipe recipe : SmithingAlchemyTableCraft.recipes) {
SmithingAlchemyTableRecipe findRecipe = recipe.findMatchingRecipe(this);
if (findRecipe != null) {
setInventorySlotContents(SmithingAlchemyTableContainer.OUTPUT_SLOT, findRecipe.getOutput().copy());
foundRecipe = true;
break;
} else {
if (recipe.matchImprovements(this, recipe.armorImprovement)) {
if (catalystSlot.getItem() instanceof ItemArmor) {
ItemStack armor = catalystSlot.copy();
if (recipe.matchCatalystForImprovements(this, armor)) {
addUpgradeItemArmor(armor, 1);
setArmorModifiers(armor, ((ItemArmor) armor.getItem()).armorType);
setInventorySlotContents(SmithingAlchemyTableContainer.OUTPUT_SLOT, armor);
foundRecipe = true;
break;
}
}
}
}
}
if (!foundRecipe) setInventorySlotContents(SmithingAlchemyTableContainer.OUTPUT_SLOT, ItemStack.EMPTY);
markDirtyAndNotify();
}
public EntityPlayer getClosestPlayer() { return world.getClosestPlayer(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 3.0, false); }
public void setFireToBrazierSoul() {
TileEntity tile = world.getTileEntity(pos.down());
if (tile != null) {
if (tile instanceof BrazierSoulTile) {
BrazierSoulTile bst = (BrazierSoulTile) tile;
setLvlFire(bst.getLvlFire());
}
} else setLvlFire(-1);
markDirtyAndNotify();
}
@Override public void readPacketNBT(NBTTagCompound nbt) {
super.readPacketNBT(nbt);
lvlFire = nbt.getInteger("LevelFire");
clientSideUpdate = nbt.getBoolean("clientSideUpdate");
customName = nbt.getString("CustomName");
}
@Override public void writePacketNBT(NBTTagCompound nbt) {
super.writePacketNBT(nbt);
nbt.setInteger("LevelFire", lvlFire);
nbt.setBoolean("clientSideUpdate", clientSideUpdate);
nbt.setString("CustomName", customName);
}
public int getLvlFire() { return this.lvlFire; }
public void setLvlFire(int lvl) { this.lvlFire = lvl; }
public String getCustomName() { return customName; }
public void setCustomName(String name) { this.customName = name; markDirty(); }
/*public void updateItemName(String newName) {
setCustomName(newName);
ItemStack catalyst = getStackInSlot(SmithingAlchemyTableContainer.CATALYST_SLOT);
if (!catalyst.isEmpty()) {
ItemStack itemstack = getStackInSlot(SmithingAlchemyTableContainer.OUTPUT_SLOT);
if (StringUtils.isBlank(newName)) itemstack.clearCustomName();
else itemstack.setStackDisplayName(getCustomName());
}
}*/
public void updateClientSide() {
if (!clientSideUpdate) return;
clientSideUpdate = false;
for (int i = 0; i < SmithingAlchemyTableContainer.INPUT_SLOT.length; i++) {
int slotIndex = SmithingAlchemyTableContainer.INPUT_SLOT[i];
ItemStack stack = getStackInSlot(slotIndex);
if (!stack.isEmpty()) { markDirty(); break; }
}
}
private int getUpgradeItemArmor(ItemStack stack) { return ItemNBTHelper.getInt(stack, "up_armor_count", 0); }
private void addUpgradeItemArmor(ItemStack stack, int count) { ItemNBTHelper.setInt(stack, "up_armor_count", getUpgradeItemArmor(stack) + count); }
}
Gui:
public class SmithingAlchemyTableGui extends GuiContainerHandler {
private static final ResourceLocation GUI_TEXTURE = new ResourceLocation(Main.MOD_ID, "textures/other/gui/inventory/smithing_alchemy_table.png");
private final int TEXTURE_WIDTH = 256;
private final int TEXTURE_HEIGHT = 256;
private static final int GUI_WIDTH = 176;
private static final int GUI_HEIGHT = 170;
private GuiTextField nameField;
private final SmithingAlchemyTableTile tile;
private final SmithingAlchemyTableContainer container;
private int guiLeft, guiTop;
public SmithingAlchemyTableGui(IInventory pInv, SmithingAlchemyTableTile tile) {
super(new SmithingAlchemyTableContainer(pInv, tile));
this.tile = tile;
this.container = (SmithingAlchemyTableContainer) this.inventorySlots;
}
@Override public void initGui() {
super.initGui();
this.guiLeft = (width - GUI_WIDTH) / 2;
this.guiTop = (height - GUI_HEIGHT + 2) / 2;
this.nameField = new GuiTextField(0, this.fontRenderer, guiLeft + 54, guiTop + 25, 103, 12);
this.nameField.setTextColor(-1);
this.nameField.setDisabledTextColour(-1);
this.nameField.setEnableBackgroundDrawing(false);
this.nameField.setMaxStringLength(60);
}
@Override protected void keyTyped(char typedChar, int keyCode) throws IOException {
/*if (this.nameField.textboxKeyTyped(typedChar, keyCode)) renameItem(); else */super.keyTyped(typedChar, keyCode);
}
/*private void renameItem() {
String s = this.nameField.getText();
Slot slot = container.getSlot(SmithingAlchemyTableContainer.CATALYST_SLOT);
if (slot != null && slot.getHasStack() && !slot.getStack().hasDisplayName() && s.equals(slot.getStack().getDisplayName())) {
s = "";
}
this.tile.updateItemName(s);
this.mc.player.connection.sendPacket(new CPacketCustomPayload("MC|ItemName", (new PacketBuffer(Unpooled.buffer())).writeString(s)));
}*/
@Override protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
super.mouseClicked(mouseX, mouseY, mouseButton);
this.nameField.mouseClicked(mouseX, mouseY, mouseButton);
}
@Override public void updateScreen() { super.updateScreen(); tile.updateClientSide(); }
@Override public void drawScreen(int mouseX, int mouseY, float partialTicks) {
this.drawDefaultBackground();
super.drawScreen(mouseX, mouseY, partialTicks);
this.renderHoveredToolTip(mouseX, mouseY);
ItemStack catalyst = tile.getStackInSlot(SmithingAlchemyTableContainer.CATALYST_SLOT);
if (!catalyst.isEmpty()) {
nameField.setText(catalyst.getDisplayName());
GlStateManager.disableLighting();
GlStateManager.disableBlend();
this.nameField.drawTextBox();
}
}
@Override protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
GlStateManager.pushMatrix();
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
mc.getTextureManager().bindTexture(GUI_TEXTURE);
int textBox = container.getSlot(0).getHasStack() ? 170 : 186;
drawScaledCustomSize(guiLeft, guiTop, 0, 0, GUI_WIDTH, GUI_HEIGHT, GUI_WIDTH, GUI_HEIGHT, TEXTURE_WIDTH, TEXTURE_HEIGHT);
drawScaledCustomSize(guiLeft + 51, guiTop + 21, 0, textBox, 110, 16, 110, 16, TEXTURE_WIDTH, TEXTURE_HEIGHT);
drawFireLevelIndicator(tile.getLvlFire());
drawExperienceTextIfApplicable();
GlStateManager.popMatrix();
}
private void drawFireLevelIndicator(int fireLevel) {
int textureY = 37 + (fireLevel * 19);
drawScaledCustomSize(guiLeft + 33, guiTop + 64, 178, textureY, 18, 18, 18, 18, TEXTURE_WIDTH, TEXTURE_HEIGHT);
}
private void drawExperienceTextIfApplicable() {
ItemStack catalyst = tile.getStackInSlot(SmithingAlchemyTableContainer.CATALYST_SLOT);
for (SmithingAlchemyTableRecipe recipe : SmithingAlchemyTableCraft.recipes) {
if (recipe.findMatchingRecipe(tile) != null) {
drawExpText(mc, width, height, recipe.findMatchingRecipe(tile));
break;
}
if (recipe.matchImprovements(tile, recipe.armorImprovement) && recipe.findMatchingRecipe(tile) == null) {
if (catalyst.getItem() instanceof ItemArmor && !catalyst.isEmpty()) {
drawExpLvlText(mc, width, height, recipe.lvlArmor);
break;
}
}
}
}
public void drawExpLvlText(Minecraft mc, int recipeWidth, int recipeHeight, int lvl) {
String text = JeiHandler.locKey(JeiHandler.SAT_RequiresExperience).concat(" " + lvl + GuiContainerHandler.EXP_LEVELS);
drawTextBox(mc, recipeWidth, recipeHeight, text, lvl);
}
public void drawExpText(Minecraft mc, int recipeWidth, int recipeHeight, SmithingAlchemyTableRecipe recipe) {
String labelText = JeiHandler.locKey(JeiHandler.SAT_RequiresExperience);
String labelTextNull = JeiHandler.locKey(JeiHandler.SAT_RequiresExperienceNull);
String expText = recipe.isExpLevel() ? recipe.getExpCost() + GuiContainerHandler.EXP_LEVELS : recipe.getExpCost() + GuiContainerHandler.EXP_POINTS;
String text = recipe.getExpCost() != 0 ? labelText.concat(" " + expText) : labelTextNull;
drawTextBox(mc, recipeWidth, recipeHeight, text, recipe);
}
private void drawTextBox(Minecraft mc, int recipeWidth, int recipeHeight, String text, int lvl) {
int BOX_PADDING = 1;
float textScale = mc.getLanguageManager().getCurrentLanguage().getLanguageCode().startsWith("ru") ? 1.0f : 0.8f;
int yOffset = mc.getLanguageManager().getCurrentLanguage().getLanguageCode().startsWith("ru") ? 6 : 7;
int labelWidth = mc.fontRenderer.getStringWidth(text) + (BOX_PADDING * 2);
int boxHeight = mc.fontRenderer.FONT_HEIGHT + (BOX_PADDING * 2);
int BASE_X = ((recipeWidth / 2) + 81) - labelWidth;
int BASE_Y = ((recipeHeight / 2) - 22) + yOffset;
GlStateManager.enableAlpha();
GlStateManager.enableBlend();
GlStateManager.pushMatrix();
GlStateManager.translate(BASE_X, BASE_Y, 0);
GlStateManager.scale(textScale, textScale, 1.0F);
drawBox(0, 0, labelWidth, boxHeight, 0x80000000);
int textColor = mc.player.experienceLevel >= lvl ? 0xFF80FF20 : 0xF51000;
mc.fontRenderer.drawStringWithShadow(text, BOX_PADDING, BOX_PADDING, textColor);
GlStateManager.popMatrix();
GlStateManager.disableBlend();
GlStateManager.disableAlpha();
}
private void drawTextBox(Minecraft mc, int recipeWidth, int recipeHeight, String text, SmithingAlchemyTableRecipe recipe) {
int BOX_PADDING = 1;
float textScale = mc.getLanguageManager().getCurrentLanguage().getLanguageCode().startsWith("ru") ? 1.0f : 0.8f;
int yOffset = mc.getLanguageManager().getCurrentLanguage().getLanguageCode().startsWith("ru") ? 6 : 7;
int labelWidth = mc.fontRenderer.getStringWidth(text) + (BOX_PADDING * 2);
int boxHeight = mc.fontRenderer.FONT_HEIGHT + (BOX_PADDING * 2);
int BASE_X = ((recipeWidth / 2) + 81) - labelWidth;
int BASE_Y = ((recipeHeight / 2) - 22) + yOffset;
GlStateManager.enableAlpha();
GlStateManager.enableBlend();
GlStateManager.pushMatrix();
GlStateManager.translate(BASE_X, BASE_Y, 0);
GlStateManager.scale(textScale, textScale, 1.0F);
drawBox(0, 0, labelWidth, boxHeight, 0x80000000);
int textColor = recipe.hasEnoughExperience(mc.player) ? 0xFF80FF20 : 0xF51000;
mc.fontRenderer.drawStringWithShadow(text, BOX_PADDING, BOX_PADDING, textColor);
GlStateManager.popMatrix();
GlStateManager.disableBlend();
GlStateManager.disableAlpha();
}
}
Container:
public class SmithingAlchemyTableContainer extends Container {
private SmithingAlchemyTableTile tile;
public static int CATALYST_SLOT = 0;
public static int[] INPUT_SLOT = {1, 2, 3};
public static int OUTPUT_SLOT = 4;
public SmithingAlchemyTableContainer(IInventory pInv, SmithingAlchemyTableTile tile) {
this.tile = tile;
addSlotToContainer(new SInput(tile, 0, 90, 44));
addSlotToContainer(new SInput(tile, 1, 16, 44));
addSlotToContainer(new SInput(tile, 2, 34, 44));
addSlotToContainer(new SInput(tile, 3, 52, 44));
addSlotToContainer(new SOutput(tile, 4, 144, 44));
for (int i = 0; i < 3; ++i) for (int j = 0; j < 9; ++j) this.addSlotToContainer(new Slot(pInv, j + i * 9 + 9, 8 + j * 18, 86 + i * 18));
for (int k = 0; k < 9; ++k) this.addSlotToContainer(new Slot(pInv, k, 8 + k * 18, 144));
}
@Override public ItemStack transferStackInSlot(EntityPlayer player, int index) {
ItemStack stack = ItemStack.EMPTY;
Slot slot = this.inventorySlots.get(index);
int sizeSlots = SmithingAlchemyTableTile.INV_SIZE;
if (slot != null && slot.getHasStack()) {
ItemStack stackToMove = slot.getStack();
stack = stackToMove.copy();
if (index >= sizeSlots && index != OUTPUT_SLOT) {
if (!this.mergeItemStack(stackToMove, 0, sizeSlots-1, false)) return ItemStack.EMPTY;
} else if (index < sizeSlots) {
if (!this.mergeItemStack(stackToMove, sizeSlots, this.inventorySlots.size(), false)) return ItemStack.EMPTY;
}
if (stackToMove.isEmpty()) slot.putStack(ItemStack.EMPTY); else slot.onSlotChanged();
if (stackToMove.getCount() == stack.getCount()) return ItemStack.EMPTY;
slot.onTake(player, stackToMove);
return stack;
}
return ItemStack.EMPTY;
}
@Override public boolean canInteractWith(@Nonnull EntityPlayer player) {
if (this.tile.getWorld().getBlockState(this.tile.getPos()).getBlock() != BlockInit.SMITHING_ALCHEMY_TABLE) return false;
else return tile.isUsableByPlayer(player);
}
private static class SInput extends Slot {
public SInput(IInventory inv, int index, int xPosition, int yPosition) { super(inv, index, xPosition, yPosition); }
@Override public boolean isItemValid(@Nonnull ItemStack is) { return true; }
}
private static class SOutput extends Slot {
public SOutput(IInventory inv, int index, int xPosition, int yPosition) { super(inv, index, xPosition, yPosition); }
@Override public boolean isItemValid(@Nonnull ItemStack is) { return false; }
@Override public ItemStack onTake(EntityPlayer player, ItemStack stack) { return processOutput(player, stack); }
@Override public boolean canTakeStack(EntityPlayer player) { return canPlayerTakeOutput(player); }
private boolean canPlayerTakeOutput(EntityPlayer player) {
SmithingAlchemyTableTile tile = (SmithingAlchemyTableTile) inventory;
player = tile.getClosestPlayer();
for (SmithingAlchemyTableRecipe recipe : SmithingAlchemyTableCraft.recipes) {
SmithingAlchemyTableRecipe findRecipe = recipe.findMatchingRecipe(tile);
if (findRecipe != null) {
if (player != null) return findRecipe.hasEnoughExperience(player);
break;
} else {
if (recipe.matchImprovements(tile, recipe.armorImprovement)) {
if (player != null) return player.experienceLevel >= recipe.lvlArmor;
break;
}
}
}
return false;
}
private ItemStack processOutput(EntityPlayer player, ItemStack stack) {
SmithingAlchemyTableTile tile = (SmithingAlchemyTableTile) inventory;
for (SmithingAlchemyTableRecipe recipe : SmithingAlchemyTableCraft.recipes) if (tryProcessCraft(recipe, tile, player)) return super.onTake(player, stack);
return ItemStack.EMPTY;
}
private boolean tryProcessCraft(SmithingAlchemyTableRecipe recipe, SmithingAlchemyTableTile tile, EntityPlayer player) {
SmithingAlchemyTableRecipe findRecipe = recipe.findMatchingRecipe(tile);
if (findRecipe != null) {
return processBasicCraft(findRecipe, tile, player);
} else {
if (recipe.matchImprovements(tile, recipe.armorImprovement)) {
return processImprovementCraft(recipe, tile, player, recipe.armorImprovement, recipe.lvlArmor);
}
}
return false;
}
private boolean processImprovementCraft(SmithingAlchemyTableRecipe recipe, SmithingAlchemyTableTile tile, EntityPlayer player, ItemStack stack, int lvl) {
ItemStack catalystSlot = tile.getStackInSlot(SmithingAlchemyTableContainer.CATALYST_SLOT);
if (player.experienceLevel >= lvl) {
player.addExperienceLevel(-lvl);
consumeInputStack(stack, recipe, tile);
catalystSlot.shrink(catalystSlot.getCount());
return true;
}
return false;
}
private boolean processBasicCraft(SmithingAlchemyTableRecipe recipe, SmithingAlchemyTableTile tile, EntityPlayer player) {
ItemStack catalystSlot = tile.getStackInSlot(SmithingAlchemyTableContainer.CATALYST_SLOT);
if (recipe.hasEnoughExperience(player)) {
recipe.consumeExperience(player);
consumeInputs(recipe, tile);
catalystSlot.shrink(recipe.getCatalystInput().getCount());
return true;
}
return false;
}
private void consumeInputStack(ItemStack stack, SmithingAlchemyTableRecipe recipe, SmithingAlchemyTableTile tile) {
List<ItemStack> remainIng = new ArrayList<>();
remainIng.add(stack.copy());
consumeStacks(remainIng, recipe, tile);
}
private void consumeInputs(SmithingAlchemyTableRecipe recipe, SmithingAlchemyTableTile tile) {
List<ItemStack> remainIng = new ArrayList<>();
for (Ingredient input : recipe.getInputs()) for (ItemStack ing : input.getMatchingStacks()) remainIng.add(ing.copy());
consumeStacks(remainIng, recipe, tile);
}
private void consumeStacks(List<ItemStack> remainIng, SmithingAlchemyTableRecipe recipe, SmithingAlchemyTableTile tile) {
for (int index : SmithingAlchemyTableContainer.INPUT_SLOT) {
ItemStack invStack = tile.getStackInSlot(index);
for (int i = 0; i < remainIng.size(); i++) {
ItemStack requiredStack = remainIng.get(i);
if (recipe.compareStacks(invStack, requiredStack)) {
invStack.shrink(requiredStack.getCount());
remainIng.remove(i);
break;
}
}
}
}
}
}
