Bläddra i källkod

接管附魔台 GUI,虽然看起来挺失败的……

LTCatt 6 år sedan
förälder
incheckning
9d7e67c761

+ 1 - 0
src/main/java/com/hexdragon/enchre/EnchRe.java

@@ -10,5 +10,6 @@ public class EnchRe {
     public EnchRe() {
         IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
         RegMain.ENCHANTMENTS.register(modEventBus);
+        RegMain.CONTAINERS.register(modEventBus);
     }
 }

+ 314 - 0
src/main/java/com/hexdragon/enchre/block/enchantingtable/EnchantmentContainerRe.java

@@ -0,0 +1,314 @@
+package com.hexdragon.enchre.block.enchantingtable;
+import net.minecraft.advancements.CriteriaTriggers;
+import net.minecraft.block.Blocks;
+import net.minecraft.enchantment.EnchantmentData;
+import net.minecraft.enchantment.EnchantmentHelper;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.entity.player.ServerPlayerEntity;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.inventory.Inventory;
+import net.minecraft.inventory.container.Container;
+import net.minecraft.inventory.container.ContainerType;
+import net.minecraft.inventory.container.Slot;
+import net.minecraft.item.EnchantedBookItem;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.Items;
+import net.minecraft.nbt.CompoundNBT;
+import net.minecraft.stats.Stats;
+import net.minecraft.util.IWorldPosCallable;
+import net.minecraft.util.IntReferenceHolder;
+import net.minecraft.util.SoundCategory;
+import net.minecraft.util.SoundEvents;
+import net.minecraft.util.registry.Registry;
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.api.distmarker.OnlyIn;
+
+import java.util.List;
+import java.util.Random;
+
+public class EnchantmentContainerRe extends Container {
+    private final IInventory tableInventory = new Inventory(2) {
+        /**
+         * For tile entities, ensures the chunk containing the tile entity is saved to disk later - the game won't think
+         * it hasn't changed and skip it.
+         */
+        public void markDirty() {
+            super.markDirty();
+            EnchantmentContainerRe.this.onCraftMatrixChanged(this);
+        }
+    };
+    private final IWorldPosCallable worldPosCallable;
+    private final Random rand = new Random();
+    private final IntReferenceHolder xpSeed = IntReferenceHolder.single();
+    public final int[] enchantLevels = new int[3];
+    public final int[] enchantClue = new int[]{-1, -1, -1};
+    public final int[] worldClue = new int[]{-1, -1, -1};
+
+    public EnchantmentContainerRe(int id, PlayerInventory playerInventory) {
+        this(id, playerInventory, IWorldPosCallable.DUMMY);
+    }
+
+    public EnchantmentContainerRe(int id, PlayerInventory playerInventory, IWorldPosCallable worldPosCallable) {
+        super(ContainerType.ENCHANTMENT, id);
+        this.worldPosCallable = worldPosCallable;
+        this.addSlot(new Slot(this.tableInventory, 0, 15, 47) {
+            /**
+             * Check if the stack is allowed to be placed in this slot, used for armor slots as well as furnace fuel.
+             */
+            public boolean isItemValid(ItemStack stack) {
+                return true;
+            }
+
+            /**
+             * Returns the maximum stack size for a given slot (usually the same as getInventoryStackLimit(), but 1 in the
+             * case of armor slots)
+             */
+            public int getSlotStackLimit() {
+                return 1;
+            }
+        });
+        this.addSlot(new Slot(this.tableInventory, 1, 35, 47) {
+            /**
+             * Check if the stack is allowed to be placed in this slot, used for armor slots as well as furnace fuel.
+             */
+            public boolean isItemValid(ItemStack stack) {
+                return net.minecraftforge.common.Tags.Items.GEMS_LAPIS.contains(stack.getItem());
+            }
+        });
+
+        for(int i = 0; i < 3; ++i) {
+            for(int j = 0; j < 9; ++j) {
+                this.addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 84 + 50 + i * 18)); // TODO : 确认附魔台 UI 已经被替换了
+            }
+        }
+
+        for(int k = 0; k < 9; ++k) {
+            this.addSlot(new Slot(playerInventory, k, 8 + k * 18, 142));
+        }
+
+        this.trackInt(IntReferenceHolder.create(this.enchantLevels, 0));
+        this.trackInt(IntReferenceHolder.create(this.enchantLevels, 1));
+        this.trackInt(IntReferenceHolder.create(this.enchantLevels, 2));
+        this.trackInt(this.xpSeed).set(playerInventory.player.getXPSeed());
+        this.trackInt(IntReferenceHolder.create(this.enchantClue, 0));
+        this.trackInt(IntReferenceHolder.create(this.enchantClue, 1));
+        this.trackInt(IntReferenceHolder.create(this.enchantClue, 2));
+        this.trackInt(IntReferenceHolder.create(this.worldClue, 0));
+        this.trackInt(IntReferenceHolder.create(this.worldClue, 1));
+        this.trackInt(IntReferenceHolder.create(this.worldClue, 2));
+    }
+
+    private float getPower(net.minecraft.world.World world, net.minecraft.util.math.BlockPos pos) {
+        return world.getBlockState(pos).getEnchantPowerBonus(world, pos);
+    }
+
+    /**
+     * Callback for when the crafting matrix is changed.
+     */
+    public void onCraftMatrixChanged(IInventory inventoryIn) {
+        if (inventoryIn == this.tableInventory) {
+            ItemStack itemstack = inventoryIn.getStackInSlot(0);
+            if (!itemstack.isEmpty() && itemstack.isEnchantable()) {
+                this.worldPosCallable.consume((p_217002_2_, p_217002_3_) -> {
+                    int power = 0;
+
+                    for(int k = -1; k <= 1; ++k) {
+                        for(int l = -1; l <= 1; ++l) {
+                            if ((k != 0 || l != 0) && p_217002_2_.isAirBlock(p_217002_3_.add(l, 0, k)) && p_217002_2_.isAirBlock(p_217002_3_.add(l, 1, k))) {
+                                power += getPower(p_217002_2_, p_217002_3_.add(l * 2, 0, k * 2));
+                                power += getPower(p_217002_2_, p_217002_3_.add(l * 2, 1, k * 2));
+
+                                if (l != 0 && k != 0) {
+                                    power += getPower(p_217002_2_, p_217002_3_.add(l * 2, 0, k));
+                                    power += getPower(p_217002_2_, p_217002_3_.add(l * 2, 1, k));
+                                    power += getPower(p_217002_2_, p_217002_3_.add(l, 0, k * 2));
+                                    power += getPower(p_217002_2_, p_217002_3_.add(l, 1, k * 2));
+                                }
+                            }
+                        }
+                    }
+
+                    this.rand.setSeed((long)this.xpSeed.get());
+
+                    for(int i1 = 0; i1 < 3; ++i1) {
+                        this.enchantLevels[i1] = EnchantmentHelper.calcItemStackEnchantability(this.rand, i1, (int)power, itemstack);
+                        this.enchantClue[i1] = -1;
+                        this.worldClue[i1] = -1;
+                        if (this.enchantLevels[i1] < i1 + 1) {
+                            this.enchantLevels[i1] = 0;
+                        }
+                        this.enchantLevels[i1] = net.minecraftforge.event.ForgeEventFactory.onEnchantmentLevelSet(p_217002_2_, p_217002_3_, i1, (int)power, itemstack, enchantLevels[i1]);
+                    }
+
+                    for(int j1 = 0; j1 < 3; ++j1) {
+                        if (this.enchantLevels[j1] > 0) {
+                            List<EnchantmentData> list = this.getEnchantmentList(itemstack, j1, this.enchantLevels[j1]);
+                            if (list != null && !list.isEmpty()) {
+                                EnchantmentData enchantmentdata = list.get(this.rand.nextInt(list.size()));
+                                this.enchantClue[j1] = Registry.ENCHANTMENT.getId(enchantmentdata.enchantment);
+                                this.worldClue[j1] = enchantmentdata.enchantmentLevel;
+                            }
+                        }
+                    }
+
+                    this.detectAndSendChanges();
+                });
+            } else {
+                for(int i = 0; i < 3; ++i) {
+                    this.enchantLevels[i] = 0;
+                    this.enchantClue[i] = -1;
+                    this.worldClue[i] = -1;
+                }
+            }
+        }
+
+    }
+
+    /**
+     * Handles the given Button-click on the server, currently only used by enchanting. Name is for legacy.
+     */
+    public boolean enchantItem(PlayerEntity playerIn, int id) {
+        ItemStack itemstack = this.tableInventory.getStackInSlot(0);
+        ItemStack itemstack1 = this.tableInventory.getStackInSlot(1);
+        int i = id + 1;
+        if ((itemstack1.isEmpty() || itemstack1.getCount() < i) && !playerIn.abilities.isCreativeMode) {
+            return false;
+        } else if (this.enchantLevels[id] <= 0 || itemstack.isEmpty() || (playerIn.experienceLevel < i || playerIn.experienceLevel < this.enchantLevels[id]) && !playerIn.abilities.isCreativeMode) {
+            return false;
+        } else {
+            this.worldPosCallable.consume((p_217003_6_, p_217003_7_) -> {
+                ItemStack itemstack2 = itemstack;
+                List<EnchantmentData> list = this.getEnchantmentList(itemstack, id, this.enchantLevels[id]);
+                if (!list.isEmpty()) {
+                    playerIn.onEnchant(itemstack, i);
+                    boolean flag = itemstack.getItem() == Items.BOOK;
+                    if (flag) {
+                        itemstack2 = new ItemStack(Items.ENCHANTED_BOOK);
+                        CompoundNBT compoundnbt = itemstack.getTag();
+                        if (compoundnbt != null) {
+                            itemstack2.setTag(compoundnbt.copy());
+                        }
+
+                        this.tableInventory.setInventorySlotContents(0, itemstack2);
+                    }
+
+                    for(int j = 0; j < list.size(); ++j) {
+                        EnchantmentData enchantmentdata = list.get(j);
+                        if (flag) {
+                            EnchantedBookItem.addEnchantment(itemstack2, enchantmentdata);
+                        } else {
+                            itemstack2.addEnchantment(enchantmentdata.enchantment, enchantmentdata.enchantmentLevel);
+                        }
+                    }
+
+                    if (!playerIn.abilities.isCreativeMode) {
+                        itemstack1.shrink(i);
+                        if (itemstack1.isEmpty()) {
+                            this.tableInventory.setInventorySlotContents(1, ItemStack.EMPTY);
+                        }
+                    }
+
+                    playerIn.addStat(Stats.ENCHANT_ITEM);
+                    if (playerIn instanceof ServerPlayerEntity) {
+                        CriteriaTriggers.ENCHANTED_ITEM.trigger((ServerPlayerEntity)playerIn, itemstack2, i);
+                    }
+
+                    this.tableInventory.markDirty();
+                    this.xpSeed.set(playerIn.getXPSeed());
+                    this.onCraftMatrixChanged(this.tableInventory);
+                    p_217003_6_.playSound((PlayerEntity)null, p_217003_7_, SoundEvents.BLOCK_ENCHANTMENT_TABLE_USE, SoundCategory.BLOCKS, 1.0F, p_217003_6_.rand.nextFloat() * 0.1F + 0.9F);
+                }
+
+            });
+            return true;
+        }
+    }
+
+    private List<EnchantmentData> getEnchantmentList(ItemStack stack, int enchantSlot, int level) {
+        this.rand.setSeed((long)(this.xpSeed.get() + enchantSlot));
+        List<EnchantmentData> list = EnchantmentHelper.buildEnchantmentList(this.rand, stack, level, false);
+        if (stack.getItem() == Items.BOOK && list.size() > 1) {
+            list.remove(this.rand.nextInt(list.size()));
+        }
+
+        return list;
+    }
+
+    @OnlyIn(Dist.CLIENT)
+    public int getLapisAmount() {
+        ItemStack itemstack = this.tableInventory.getStackInSlot(1);
+        return itemstack.isEmpty() ? 0 : itemstack.getCount();
+    }
+
+    @OnlyIn(Dist.CLIENT)
+    public int func_217005_f() {
+        return this.xpSeed.get();
+    }
+
+    /**
+     * Called when the container is closed.
+     */
+    public void onContainerClosed(PlayerEntity playerIn) {
+        super.onContainerClosed(playerIn);
+        this.worldPosCallable.consume((p_217004_2_, p_217004_3_) -> {
+            this.clearContainer(playerIn, playerIn.world, this.tableInventory);
+        });
+    }
+
+    /**
+     * Determines whether supplied player can use this container
+     */
+    public boolean canInteractWith(PlayerEntity playerIn) {
+        return isWithinUsableDistance(this.worldPosCallable, playerIn, Blocks.ENCHANTING_TABLE);
+    }
+
+    /**
+     * Handle when the stack in slot {@code index} is shift-clicked. Normally this moves the stack between the player
+     * inventory and the other inventory(s).
+     */
+    public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) {
+        ItemStack itemstack = ItemStack.EMPTY;
+        Slot slot = this.inventorySlots.get(index);
+        if (slot != null && slot.getHasStack()) {
+            ItemStack itemstack1 = slot.getStack();
+            itemstack = itemstack1.copy();
+            if (index == 0) {
+                if (!this.mergeItemStack(itemstack1, 2, 38, true)) {
+                    return ItemStack.EMPTY;
+                }
+            } else if (index == 1) {
+                if (!this.mergeItemStack(itemstack1, 2, 38, true)) {
+                    return ItemStack.EMPTY;
+                }
+            } else if (itemstack1.getItem() == Items.LAPIS_LAZULI) {
+                if (!this.mergeItemStack(itemstack1, 1, 2, true)) {
+                    return ItemStack.EMPTY;
+                }
+            } else {
+                if (this.inventorySlots.get(0).getHasStack() || !this.inventorySlots.get(0).isItemValid(itemstack1)) {
+                    return ItemStack.EMPTY;
+                }
+
+                ItemStack itemstack2 = itemstack1.copy();
+                itemstack2.setCount(1);
+                itemstack1.shrink(1);
+                this.inventorySlots.get(0).putStack(itemstack2);
+            }
+
+            if (itemstack1.isEmpty()) {
+                slot.putStack(ItemStack.EMPTY);
+            } else {
+                slot.onSlotChanged();
+            }
+
+            if (itemstack1.getCount() == itemstack.getCount()) {
+                return ItemStack.EMPTY;
+            }
+
+            slot.onTake(playerIn, itemstack1);
+        }
+
+        return itemstack;
+    }
+}

+ 266 - 0
src/main/java/com/hexdragon/enchre/block/enchantingtable/EnchantmentScreenRe.java

@@ -0,0 +1,266 @@
+package com.hexdragon.enchre.block.enchantingtable;
+
+import com.google.common.collect.Lists;
+import com.mojang.blaze3d.matrix.MatrixStack;
+import com.mojang.blaze3d.systems.RenderSystem;
+import com.mojang.blaze3d.vertex.IVertexBuilder;
+import java.util.List;
+import java.util.Random;
+import net.minecraft.client.gui.screen.inventory.ContainerScreen;
+import net.minecraft.client.renderer.IRenderTypeBuffer;
+import net.minecraft.client.renderer.RenderHelper;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.entity.model.BookModel;
+import net.minecraft.client.renderer.texture.OverlayTexture;
+import net.minecraft.enchantment.Enchantment;
+import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.inventory.container.EnchantmentContainer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnchantmentNameParts;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.util.math.MathHelper;
+import net.minecraft.util.math.vector.Matrix4f;
+import net.minecraft.util.math.vector.Vector3f;
+import net.minecraft.util.text.IFormattableTextComponent;
+import net.minecraft.util.text.ITextComponent;
+import net.minecraft.util.text.ITextProperties;
+import net.minecraft.util.text.StringTextComponent;
+import net.minecraft.util.text.TextFormatting;
+import net.minecraft.util.text.TranslationTextComponent;
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.api.distmarker.OnlyIn;
+
+@OnlyIn(Dist.CLIENT)
+public class EnchantmentScreenRe extends ContainerScreen<EnchantmentContainerRe> {
+    /** The ResourceLocation containing the Enchantment GUI texture location */
+    private static final ResourceLocation ENCHANTMENT_TABLE_GUI_TEXTURE = new ResourceLocation("textures/gui/container/enchanting_table.png");
+    /** The ResourceLocation containing the texture for the Book rendered above the enchantment table */
+    private static final ResourceLocation ENCHANTMENT_TABLE_BOOK_TEXTURE = new ResourceLocation("textures/entity/enchanting_table_book.png");
+    /** The ModelBook instance used for rendering the book on the Enchantment table */
+    private static final BookModel MODEL_BOOK = new BookModel();
+    /** A Random instance for use with the enchantment gui */
+    private final Random random = new Random();
+    public int ticks;
+    public float flip;
+    public float oFlip;
+    public float flipT;
+    public float flipA;
+    public float open;
+    public float oOpen;
+    private ItemStack last = ItemStack.EMPTY;
+
+    public EnchantmentScreenRe(EnchantmentContainerRe container, PlayerInventory playerInventory, ITextComponent textComponent) {
+        super(container, playerInventory, textComponent);
+    }
+
+    public void tick() {
+        super.tick();
+        this.tickBook();
+    }
+
+    public boolean mouseClicked(double mouseX, double mouseY, int button) {
+        int i = (this.width - this.xSize) / 2;
+        int j = (this.height - this.ySize) / 2;
+
+        for(int k = 0; k < 3; ++k) {
+            double d0 = mouseX - (double)(i + 60);
+            double d1 = mouseY - (double)(j + 14 + 19 * k);
+            if (d0 >= 0.0D && d1 >= 0.0D && d0 < 108.0D && d1 < 19.0D && this.container.enchantItem(this.minecraft.player, k)) {
+                this.minecraft.playerController.sendEnchantPacket((this.container).windowId, k);
+                return true;
+            }
+        }
+
+        return super.mouseClicked(mouseX, mouseY, button);
+    }
+
+    protected void drawGuiContainerBackgroundLayer(MatrixStack matrixStack, float partialTicks, int x, int y) {
+        RenderHelper.setupGuiFlatDiffuseLighting();
+        RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
+        this.minecraft.getTextureManager().bindTexture(ENCHANTMENT_TABLE_GUI_TEXTURE);
+        int i = (this.width - this.xSize) / 2;
+        int j = (this.height - this.ySize) / 2;
+        this.blit(matrixStack, i, j, 0, 0, this.xSize, this.ySize);
+        RenderSystem.matrixMode(5889);
+        RenderSystem.pushMatrix();
+        RenderSystem.loadIdentity();
+        int k = (int)this.minecraft.getMainWindow().getGuiScaleFactor();
+        RenderSystem.viewport((this.width - 320) / 2 * k, (this.height - 240) / 2 * k, 320 * k, 240 * k);
+        RenderSystem.translatef(-0.34F, 0.23F, 0.0F);
+        RenderSystem.multMatrix(Matrix4f.perspective(90.0D, 1.3333334F, 9.0F, 80.0F));
+        RenderSystem.matrixMode(5888);
+        matrixStack.push();
+        MatrixStack.Entry matrixstack$entry = matrixStack.getLast();
+        matrixstack$entry.getMatrix().setIdentity();
+        matrixstack$entry.getNormal().setIdentity();
+        matrixStack.translate(0.0D, (double)3.3F, 1984.0D);
+        float f = 5.0F;
+        matrixStack.scale(5.0F, 5.0F, 5.0F);
+        matrixStack.rotate(Vector3f.ZP.rotationDegrees(180.0F));
+        matrixStack.rotate(Vector3f.XP.rotationDegrees(20.0F));
+        float f1 = MathHelper.lerp(partialTicks, this.oOpen, this.open);
+        matrixStack.translate((double)((1.0F - f1) * 0.2F), (double)((1.0F - f1) * 0.1F), (double)((1.0F - f1) * 0.25F));
+        float f2 = -(1.0F - f1) * 90.0F - 90.0F;
+        matrixStack.rotate(Vector3f.YP.rotationDegrees(f2));
+        matrixStack.rotate(Vector3f.XP.rotationDegrees(180.0F));
+        float f3 = MathHelper.lerp(partialTicks, this.oFlip, this.flip) + 0.25F;
+        float f4 = MathHelper.lerp(partialTicks, this.oFlip, this.flip) + 0.75F;
+        f3 = (f3 - (float)MathHelper.fastFloor((double)f3)) * 1.6F - 0.3F;
+        f4 = (f4 - (float)MathHelper.fastFloor((double)f4)) * 1.6F - 0.3F;
+        if (f3 < 0.0F) {
+            f3 = 0.0F;
+        }
+
+        if (f4 < 0.0F) {
+            f4 = 0.0F;
+        }
+
+        if (f3 > 1.0F) {
+            f3 = 1.0F;
+        }
+
+        if (f4 > 1.0F) {
+            f4 = 1.0F;
+        }
+
+        RenderSystem.enableRescaleNormal();
+        MODEL_BOOK.setBookState(0.0F, f3, f4, f1);
+        IRenderTypeBuffer.Impl irendertypebuffer$impl = IRenderTypeBuffer.getImpl(Tessellator.getInstance().getBuffer());
+        IVertexBuilder ivertexbuilder = irendertypebuffer$impl.getBuffer(MODEL_BOOK.getRenderType(ENCHANTMENT_TABLE_BOOK_TEXTURE));
+        MODEL_BOOK.render(matrixStack, ivertexbuilder, 15728880, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F);
+        irendertypebuffer$impl.finish();
+        matrixStack.pop();
+        RenderSystem.matrixMode(5889);
+        RenderSystem.viewport(0, 0, this.minecraft.getMainWindow().getFramebufferWidth(), this.minecraft.getMainWindow().getFramebufferHeight());
+        RenderSystem.popMatrix();
+        RenderSystem.matrixMode(5888);
+        RenderHelper.setupGui3DDiffuseLighting();
+        RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
+        EnchantmentNameParts.getInstance().reseedRandomGenerator((long)this.container.func_217005_f());
+        int l = this.container.getLapisAmount();
+
+        for(int i1 = 0; i1 < 3; ++i1) {
+            int j1 = i + 60;
+            int k1 = j1 + 20;
+            this.setBlitOffset(0);
+            this.minecraft.getTextureManager().bindTexture(ENCHANTMENT_TABLE_GUI_TEXTURE);
+            int l1 = (this.container).enchantLevels[i1];
+            RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
+            if (l1 == 0) {
+                this.blit(matrixStack, j1, j + 14 + 19 * i1, 0, 185, 108, 19);
+            } else {
+                String s = "" + l1;
+                int i2 = 86 - this.font.getStringWidth(s);
+                ITextProperties itextproperties = EnchantmentNameParts.getInstance().getGalacticEnchantmentName(this.font, i2);
+                int j2 = 6839882;
+                if (((l < i1 + 1 || this.minecraft.player.experienceLevel < l1) && !this.minecraft.player.abilities.isCreativeMode) || this.container.enchantClue[i1] == -1) { // Forge: render buttons as disabled when enchantable but enchantability not met on lower levels
+                    this.blit(matrixStack, j1, j + 14 + 19 * i1, 0, 185, 108, 19);
+                    this.blit(matrixStack, j1 + 1, j + 15 + 19 * i1, 16 * i1, 239, 16, 16);
+                    this.font.func_238418_a_(itextproperties, k1, j + 16 + 19 * i1, i2, (j2 & 16711422) >> 1);
+                    j2 = 4226832;
+                } else {
+                    int k2 = x - (i + 60);
+                    int l2 = y - (j + 14 + 19 * i1);
+                    if (k2 >= 0 && l2 >= 0 && k2 < 108 && l2 < 19) {
+                        this.blit(matrixStack, j1, j + 14 + 19 * i1, 0, 204, 108, 19);
+                        j2 = 16777088;
+                    } else {
+                        this.blit(matrixStack, j1, j + 14 + 19 * i1, 0, 166, 108, 19);
+                    }
+
+                    this.blit(matrixStack, j1 + 1, j + 15 + 19 * i1, 16 * i1, 223, 16, 16);
+                    this.font.func_238418_a_(itextproperties, k1, j + 16 + 19 * i1, i2, j2);
+                    j2 = 8453920;
+                }
+
+                this.font.drawStringWithShadow(matrixStack, s, (float)(k1 + 86 - this.font.getStringWidth(s)), (float)(j + 16 + 19 * i1 + 7), j2);
+            }
+        }
+
+    }
+
+    public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
+        partialTicks = this.minecraft.getRenderPartialTicks();
+        this.renderBackground(matrixStack);
+        super.render(matrixStack, mouseX, mouseY, partialTicks);
+        this.renderHoveredTooltip(matrixStack, mouseX, mouseY);
+        boolean flag = this.minecraft.player.abilities.isCreativeMode;
+        int i = this.container.getLapisAmount();
+
+        for(int j = 0; j < 3; ++j) {
+            int k = (this.container).enchantLevels[j];
+            Enchantment enchantment = Enchantment.getEnchantmentByID((this.container).enchantClue[j]);
+            int l = (this.container).worldClue[j];
+            int i1 = j + 1;
+            if (this.isPointInRegion(60, 14 + 19 * j, 108, 17, (double)mouseX, (double)mouseY) && k > 0) {
+                List<ITextComponent> list = Lists.newArrayList();
+                list.add((new TranslationTextComponent("container.enchant.clue", enchantment == null ? "" : enchantment.getDisplayName(l))).mergeStyle(TextFormatting.WHITE));
+                if(enchantment == null) {
+                    list.add(new StringTextComponent(""));
+                    list.add(new TranslationTextComponent("forge.container.enchant.limitedEnchantability").mergeStyle(TextFormatting.RED));
+                } else if (!flag) {
+                    list.add(StringTextComponent.EMPTY);
+                    if (this.minecraft.player.experienceLevel < k) {
+                        list.add((new TranslationTextComponent("container.enchant.level.requirement", (this.container).enchantLevels[j])).mergeStyle(TextFormatting.RED));
+                    } else {
+                        IFormattableTextComponent iformattabletextcomponent;
+                        if (i1 == 1) {
+                            iformattabletextcomponent = new TranslationTextComponent("container.enchant.lapis.one");
+                        } else {
+                            iformattabletextcomponent = new TranslationTextComponent("container.enchant.lapis.many", i1);
+                        }
+
+                        list.add(iformattabletextcomponent.mergeStyle(i >= i1 ? TextFormatting.GRAY : TextFormatting.RED));
+                        IFormattableTextComponent iformattabletextcomponent1;
+                        if (i1 == 1) {
+                            iformattabletextcomponent1 = new TranslationTextComponent("container.enchant.level.one");
+                        } else {
+                            iformattabletextcomponent1 = new TranslationTextComponent("container.enchant.level.many", i1);
+                        }
+
+                        list.add(iformattabletextcomponent1.mergeStyle(TextFormatting.GRAY));
+                    }
+                }
+
+                this.func_243308_b(matrixStack, list, mouseX, mouseY);
+                break;
+            }
+        }
+
+    }
+
+    public void tickBook() {
+        ItemStack itemstack = this.container.getSlot(0).getStack();
+        if (!ItemStack.areItemStacksEqual(itemstack, this.last)) {
+            this.last = itemstack;
+
+            do {
+                this.flipT += (float)(this.random.nextInt(4) - this.random.nextInt(4));
+            } while(this.flip <= this.flipT + 1.0F && this.flip >= this.flipT - 1.0F);
+        }
+
+        ++this.ticks;
+        this.oFlip = this.flip;
+        this.oOpen = this.open;
+        boolean flag = false;
+
+        for(int i = 0; i < 3; ++i) {
+            if ((this.container).enchantLevels[i] != 0) {
+                flag = true;
+            }
+        }
+
+        if (flag) {
+            this.open += 0.2F;
+        } else {
+            this.open -= 0.2F;
+        }
+
+        this.open = MathHelper.clamp(this.open, 0.0F, 1.0F);
+        float f1 = (this.flipT - this.flip) * 0.4F;
+        float f = 0.2F;
+        f1 = MathHelper.clamp(f1, -0.2F, 0.2F);
+        this.flipA += (f1 - this.flipA) * 0.9F;
+        this.flip += this.flipA;
+    }
+}

+ 31 - 0
src/main/java/com/hexdragon/enchre/mixin/block/EnchantingTableBlockMixin.java

@@ -0,0 +1,31 @@
+package com.hexdragon.enchre.mixin.block;
+import net.minecraft.block.BlockState;
+import net.minecraft.block.ContainerBlock;
+import net.minecraft.block.EnchantingTableBlock;
+import net.minecraft.inventory.container.EnchantmentContainer;
+import net.minecraft.inventory.container.INamedContainerProvider;
+import net.minecraft.inventory.container.SimpleNamedContainerProvider;
+import net.minecraft.tileentity.EnchantingTableTileEntity;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.IWorldPosCallable;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.text.TranslationTextComponent;
+import net.minecraft.world.World;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Overwrite;
+
+@Mixin(EnchantingTableBlock.class)
+public abstract class EnchantingTableBlockMixin extends ContainerBlock {
+    protected EnchantingTableBlockMixin(Properties builder) {super(builder);}
+
+    // 将附魔台的处理事件替换为 Mod 所提供的事件
+    @Overwrite public INamedContainerProvider getContainer(BlockState state, World worldIn, BlockPos pos) {
+        TileEntity tileentity = worldIn.getTileEntity(pos);
+        if (tileentity instanceof EnchantingTableTileEntity) {
+            return new SimpleNamedContainerProvider((id, inventory, player) -> new EnchantmentContainer(id, inventory, IWorldPosCallable.of(worldIn, pos)), new TranslationTextComponent("gui.enchanting.title"));
+        } else {
+            return null;
+        }
+    }
+
+}

+ 5 - 1
src/main/java/com/hexdragon/enchre/registry/RegClient.java

@@ -1,6 +1,10 @@
 package com.hexdragon.enchre.registry;
 
 import com.hexdragon.enchre.Main;
+import com.hexdragon.enchre.block.enchantingtable.EnchantmentContainerRe;
+import com.hexdragon.enchre.block.enchantingtable.EnchantmentScreenRe;
+import net.minecraft.client.gui.ScreenManager;
+import net.minecraft.client.gui.screen.EnchantmentScreen;
 import net.minecraftforge.api.distmarker.Dist;
 import net.minecraftforge.api.distmarker.OnlyIn;
 import net.minecraftforge.eventbus.api.SubscribeEvent;
@@ -12,7 +16,7 @@ public class RegClient {
 
     @SubscribeEvent public static void clientSetup(final FMLClientSetupEvent e) {
         // 注册容器的 Screen
-        // ScreenManager.registerFactory(RegMain.containerGrindstone.get(), GrindstoneScreenRe::new);
+        ScreenManager.registerFactory(RegMain.containerEnchantment.get(), EnchantmentScreenRe::new);
     }
 
 }

+ 10 - 0
src/main/java/com/hexdragon/enchre/registry/RegMain.java

@@ -1,12 +1,22 @@
 package com.hexdragon.enchre.registry;
 
 import com.hexdragon.enchre.Main;
+import com.hexdragon.enchre.block.enchantingtable.EnchantmentContainerRe;
 import net.minecraft.enchantment.Enchantment;
+import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.inventory.container.ContainerType;
+import net.minecraft.network.PacketBuffer;
+import net.minecraftforge.common.extensions.IForgeContainerType;
+import net.minecraftforge.fml.RegistryObject;
 import net.minecraftforge.registries.DeferredRegister;
 import net.minecraftforge.registries.ForgeRegistries;
 
 public class RegMain {
 
+    // Container
+    public static final DeferredRegister<ContainerType<?>> CONTAINERS = DeferredRegister.create(ForgeRegistries.CONTAINERS, Main.MODID);
+    public static final RegistryObject<ContainerType<EnchantmentContainerRe>> containerEnchantment = CONTAINERS.register("enchantment", () -> IForgeContainerType.create((int windowId, PlayerInventory inv, PacketBuffer data) -> new EnchantmentContainerRe(windowId, inv)));
+
     // 附魔
     public static final DeferredRegister<Enchantment> ENCHANTMENTS = DeferredRegister.create(ForgeRegistries.ENCHANTMENTS, Main.MODID);
     // public static final RegistryObject<Enchantment> enchDecay = ENCHANTMENTS.register("decay_curse", DecayCurseEnchantment::new);

+ 3 - 0
src/main/resources/assets/enchre/lang/zh_CN.json

@@ -0,0 +1,3 @@
+{
+  "gui.enchanting.title": "附魔"
+}