Minecraft 1.12.2模组开发(三十九) 反应器(TileEntity方块实体)

说到方块实体(TileEntity),可以理解为一种功能性方块,比如熔炉,箱子,附魔台等。

我们今天来做一个类似于熔炉的反应器

熔炉逻辑: 放入燃料-> 放入物品 -> 获取产出物品

Minecraft 1.12.2模组开发(三十九) 反应器(TileEntity方块实体)_第1张图片

1.首先我们发现熔炉有一个GUI界面,所以我们也要给自己的机器先准备一个GUI界面,可以用PS等软件进行制作(大小为256×256,在教程最后可以直接下载):

Minecraft 1.12.2模组开发(三十九) 反应器(TileEntity方块实体)_第2张图片

将做好的GUI界面放入src\main\resources\assets\你的modid\textures\gui这个地址下:

Minecraft 1.12.2模组开发(三十九) 反应器(TileEntity方块实体)_第3张图片

2.在开发包的blocks文件夹下新建tileEntity包 -> tileEntity包内新建ContainerVirusGenerator类:

由于我们这次准备了4个物品槽用于反应,1个为燃料槽(2号),2个为原料槽(0号、1号),1个为产物槽(3号):

你可以修改每个槽的x,y坐标来进行修改,但同时你要修改自己的第1步中的GUI贴图。

Minecraft 1.12.2模组开发(三十九) 反应器(TileEntity方块实体)_第4张图片
ContainerVirusGenerator.java

package com.joy187.rejoymod.blocks.tileEntity.virusGenerator;

import com.joy187.rejoymod.recipe.special.VirusGeneratorRecipes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IContainerListener;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.SlotItemHandler;

public class ContainerVirusGenerator extends Container {
    private final TileEntityVirusGenerator tileentity;
    //我们做的是类熔炉的机器,所以设置4个参数:熔炼时间,熔炼要求时间,燃料时间,当前燃烧时间
    private int cookTime, totalCookTime, burnTime, currentBurnTime;

    public ContainerVirusGenerator(InventoryPlayer player, TileEntityVirusGenerator tileentity)
    {
        this.tileentity = tileentity;
        IItemHandler handler = tileentity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
        //设置物品槽的总数与每个槽位的编号、坐标
        this.addSlotToContainer(new SlotItemHandler(handler, 0, 26, 11));
        this.addSlotToContainer(new SlotItemHandler(handler, 1, 26, 59));
        this.addSlotToContainer(new SlotItemHandler(handler, 2, 7, 35));
        this.addSlotToContainer(new SlotItemHandler(handler, 3, 81, 36));
        
        //把Inventory中的三行物品栏和一行个人栏展示出来
        for(int y = 0; y < 3; y++)
        {
            for(int x = 0; x < 9; x++)
            {
                this.addSlotToContainer(new Slot(player, x + y*9 + 9, 8 + x*18, 84 + y*18));
            }
        }

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

    @Override
    public void detectAndSendChanges()
    {
        super.detectAndSendChanges();

        for(int i = 0; i < this.listeners.size(); ++i)
        {
            IContainerListener listener = (IContainerListener)this.listeners.get(i);
            //我们一共有4个参数,所以要监视这4个参数的实时状态
            if(this.cookTime != this.tileentity.getField(2)) listener.sendWindowProperty(this, 2, this.tileentity.getField(2));
            if(this.burnTime != this.tileentity.getField(0)) listener.sendWindowProperty(this, 0, this.tileentity.getField(0));
            if(this.currentBurnTime != this.tileentity.getField(1)) listener.sendWindowProperty(this, 1, this.tileentity.getField(1));
            if(this.totalCookTime != this.tileentity.getField(3)) listener.sendWindowProperty(this, 3, this.tileentity.getField(3));
        }
        
        this.cookTime = this.tileentity.getField(2);
        this.burnTime = this.tileentity.getField(0);
        this.currentBurnTime = this.tileentity.getField(1);
        this.totalCookTime = this.tileentity.getField(3);
    }

    @Override
    @SideOnly(Side.CLIENT)
    public void updateProgressBar(int id, int data)
    {
        this.tileentity.setField(id, data);
    }

    @Override
    public boolean canInteractWith(EntityPlayer playerIn)
    {
        return this.tileentity.isUsableByPlayer(playerIn);
    }

    @Override
    public ItemStack transferStackInSlot(EntityPlayer playerIn, int index)
    {
        ItemStack stack = ItemStack.EMPTY;
        Slot slot = (Slot)this.inventorySlots.get(index);

        if(slot != null && slot.getHasStack())
        {
            ItemStack stack1 = slot.getStack();
            stack = stack1.copy();

            if(index == 3)
            {
                if(!this.mergeItemStack(stack1, 4, 40, true)) return ItemStack.EMPTY;
                slot.onSlotChange(stack1, stack);
            }
            else if(index != 2 && index != 1 && index != 0)
            {
                Slot slot1 = (Slot)this.inventorySlots.get(index + 1);

                if(!VirusGeneratorRecipes.getInstance().getSinteringResult(stack1, slot1.getStack()).isEmpty())
                {
                    if(!this.mergeItemStack(stack1, 0, 2, false))
                    {
                        return ItemStack.EMPTY;
                    }
                    else if(TileEntityVirusGenerator.isItemFuel(stack1))
                    {
                        if(!this.mergeItemStack(stack1, 2, 3, false)) return ItemStack.EMPTY;
                    }
                    else if(TileEntityVirusGenerator.isItemFuel(stack1))
                    {
                        if(!this.mergeItemStack(stack1, 2, 3, false)) return ItemStack.EMPTY;
                    }
                    else if(TileEntityVirusGenerator.isItemFuel(stack1))
                    {
                        if(!this.mergeItemStack(stack1, 2, 3, false)) return ItemStack.EMPTY;
                    }
                    else if(index >= 4 && index < 31)
                    {
                        if(!this.mergeItemStack(stack1, 31, 40, false)) return ItemStack.EMPTY;
                    }
                    else if(index >= 31 && index < 40 && !this.mergeItemStack(stack1, 4, 31, false))
                    {
                        return ItemStack.EMPTY;
                    }
                }
            }
            else if(!this.mergeItemStack(stack1, 4, 40, false))
            {
                return ItemStack.EMPTY;
            }
            if(stack1.isEmpty())
            {
                slot.putStack(ItemStack.EMPTY);
            }
            else
            {
                slot.onSlotChanged();

            }
            if(stack1.getCount() == stack.getCount()) return ItemStack.EMPTY;
            slot.onTake(playerIn, stack1);
        }
        return stack;
    }
}

同时在tileEntity包内新建GuiVirusGenerator类:

GuiVirusGenerator.java

package com.joy187.rejoymod.blocks.tileEntity.virusGenerator;


import com.joy187.rejoymod.util.Reference;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.util.ResourceLocation;
public class GuiVirusGenerator extends GuiContainer
{
    //将第一步的GUI界面的路径传给TEXTURES
    private static final ResourceLocation TEXTURES = new ResourceLocation(Reference.Mod_ID + ":textures/gui/virus_generator.png");
    private final InventoryPlayer player;
    private final TileEntityVirusGenerator tileentity;

    public GuiVirusGenerator(InventoryPlayer player, TileEntityVirusGenerator tileentity)
    {
        super(new ContainerVirusGenerator(player, tileentity));
        this.player = player;
        this.tileentity = tileentity;
    }
    
    @Override
    protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY)
    {
        String tileName = this.tileentity.getDisplayName().getUnformattedText();
        //在GUI界面的上方显示出机器的名字
        this.fontRenderer.drawString(tileName, (this.xSize / 2 - this.fontRenderer.getStringWidth(tileName) / 2) + 3, 8, 4210752);
        this.fontRenderer.drawString(this.player.getDisplayName().getUnformattedText(), 122, this.ySize - 96 + 2, 4210752);
    }
    
    //显示出整个GUI界面
    @Override
    protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY)
    {
        GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
        this.mc.getTextureManager().bindTexture(TEXTURES);
        this.drawTexturedModalRect(this.guiLeft, this.guiTop, 0, 0, this.xSize, this.ySize);

        if(TileEntityVirusGenerator.isBurning(tileentity))
        {
            int k = this.getBurnLeftScaled(13);
            this.drawTexturedModalRect(this.guiLeft + 8, this.guiTop + 54 + 12 - k, 176, 12 - k, 14, k + 1);
        }

        int l = this.getCookProgressScaled(24);
        this.drawTexturedModalRect(this.guiLeft + 44, this.guiTop + 36, 176, 14, l + 1, 16);
    }

    private int getBurnLeftScaled(int pixels)
    {
        int i = this.tileentity.getField(1);
        if(i == 0) i = 200;
        return this.tileentity.getField(0) * pixels / i;
    }

    private int getCookProgressScaled(int pixels)
    {
        int i = this.tileentity.getField(2);
        int j = this.tileentity.getField(3);
        return j != 0 && i != 0 ? i * pixels / j : 0;
    }
}

3.GUI做好之后我们开始定义一个机器类,在tileEntity包内新建TileEntityVirusGenerator类:

TileEntityVirusGenerator.java

package com.joy187.rejoymod.blocks.tileEntity.virusGenerator;


import com.joy187.rejoymod.item.ModItems;
import com.joy187.rejoymod.recipe.special.VirusGeneratorRecipes;
import net.minecraft.block.BlockFurnace;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.*;
import net.minecraft.item.crafting.FurnaceRecipes;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ITickable;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.ItemStackHandler;

public class TileEntityVirusGenerator extends TileEntity implements ITickable
{
    //与我们的GUI设计保持一致,本教程是一共4个槽位,你可以自己设计GUI和槽位数量
    public ItemStackHandler handler = new ItemStackHandler(4);
    private String customName;
    private ItemStack smelting = ItemStack.EMPTY;

    private int burnTime;
    private int currentBurnTime;
    private int cookTime;
    //默认烧好一个物品的时间是200tick
    private int totalCookTime = 200;

    @Override
    public boolean hasCapability(Capability capability, EnumFacing facing)
    {
        if(capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return true;
        else return false;
    }

    @Override
    public  T getCapability(Capability capability, EnumFacing facing)
    {
        if(capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return (T) this.handler;
        return super.getCapability(capability, facing);
    }

    public boolean hasCustomName()
    {
        return this.customName != null && !this.customName.isEmpty();
    }

    public void setCustomName(String customName)
    {
        this.customName = customName;
    }

    @Override
    public ITextComponent getDisplayName()
    {
        return this.hasCustomName() ? new TextComponentString(this.customName) : new TextComponentTranslation("container.virus_generator");
    }

    //因为我们一共有四个参数(burnTime、cookTime、totalCookTime、currentBurnTime),都要加入NBT标签
    @Override
    public void readFromNBT(NBTTagCompound compound)
    {
        super.readFromNBT(compound);
        this.handler.deserializeNBT(compound.getCompoundTag("Inventory"));
        this.burnTime = compound.getInteger("BurnTime");
        this.cookTime = compound.getInteger("CookTime");
        this.totalCookTime = compound.getInteger("CookTimeTotal");
        this.currentBurnTime = getItemBurnTime((ItemStack)this.handler.getStackInSlot(2));

        if(compound.hasKey("CustomName", 8)) this.setCustomName(compound.getString("CustomName"));
    }

    @Override
    public NBTTagCompound writeToNBT(NBTTagCompound compound)
    {
        super.writeToNBT(compound);
        compound.setInteger("BurnTime", (short)this.burnTime);
        compound.setInteger("CookTime", (short)this.cookTime);
        compound.setInteger("CookTimeTotal", (short)this.totalCookTime);
        compound.setTag("Inventory", this.handler.serializeNBT());

        if(this.hasCustomName()) compound.setString("CustomName", this.customName);
        return compound;
    }

    public boolean isBurning()
    {
        return this.burnTime > 0;
    }

    @SideOnly(Side.CLIENT)
    public static boolean isBurning(TileEntityVirusGenerator tile)
    {
        return tile.getField(0) > 0;
    }
    //对机器燃烧的状态进行实时更新
    public void update()
    {
        boolean flag = this.isBurning();
        boolean flag1 = false;

        if (this.isBurning())
        {
            --this.burnTime;
        }

        if (!this.world.isRemote)
        {
            ItemStack[] itemstack = new ItemStack[] {handler.getStackInSlot(0), handler.getStackInSlot(1)};
            ItemStack fuel = this.handler.getStackInSlot(2);

            if (this.isBurning() || !fuel.isEmpty() && !this.handler.getStackInSlot(0).isEmpty() || this.handler.getStackInSlot(1).isEmpty())
            {
                if (!this.isBurning() && this.canSmelt())
                {
                    this.burnTime = getItemBurnTime(fuel);
                    this.currentBurnTime = this.burnTime;

                    if (this.isBurning())
                    {
                        flag1 = true;

                        if (!fuel.isEmpty())
                        {
                            Item item = fuel.getItem();
                            fuel.shrink(1);

                            if (fuel.isEmpty())
                            {
                                ItemStack item1 = item.getContainerItem(fuel);
                                this.handler.setStackInSlot(2, item1);
                            }
                        }
                    }
                }

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

                    if (this.cookTime == this.totalCookTime)
                    {
                        //熔炼时间达到了熔炼要求时间,就在3号槽产出一个产物
                        this.cookTime = 0;
                        this.totalCookTime = this.getCookTime(this.handler.getStackInSlot(2));
                        this.smeltItem();
                        flag1 = true;
                    }
                }
                else
                {
                    this.cookTime = 0;
                }
            }
            else if (!this.isBurning() && this.cookTime > 0)
            {
                this.cookTime = MathHelper.clamp(this.cookTime - 2, 0, this.totalCookTime);
            }

            if (flag != this.isBurning())
            {
                flag1 = true;
                BlockVirusGenerator.setState(this.isBurning(), this.world, this.pos);
            }
        }

        if (flag1)
        {
            this.markDirty();
        }
    }
    private boolean canSmelt()
    {

        if(((ItemStack)this.handler.getStackInSlot(0)).isEmpty() || ((ItemStack)this.handler.getStackInSlot(1)).isEmpty())
        {
            return false;
        }
        else
        {
            ItemStack result = VirusGeneratorRecipes.getInstance().getSinteringResult((ItemStack)this.handler.getStackInSlot(0), (ItemStack)this.handler.getStackInSlot(1));

            if (result.isEmpty())
            {
                return false;
            }
            else
            {
                ItemStack output = (ItemStack)this.handler.getStackInSlot(3);

                if (output.isEmpty())
                {
                    return true;
                }
                else if (!output.isItemEqual(result))
                {
                    return false;
                }
                else if (output.getCount() + result.getCount() <= 64 && output.getCount() + result.getCount() <= output.getMaxStackSize())  // Forge fix: make furnace respect stack sizes in furnace recipes
                {
                    return true;
                }
                else
                {
                    return output.getCount() + result.getCount() <= output.getMaxStackSize(); // Forge fix: make furnace respect stack sizes in furnace recipes
                }
            }
        }
    }

    public void smeltItem()
    {
        if (this.canSmelt())
        {
            ItemStack[] itemstack = new ItemStack[] {handler.getStackInSlot(0), handler.getStackInSlot(1)};
            ItemStack itemstack1 = VirusGeneratorRecipes.getInstance().getSinteringResult((ItemStack)this.handler.getStackInSlot(0), (ItemStack)this.handler.getStackInSlot(1));
            ItemStack itemstack2 = this.handler.getStackInSlot(3);

            if (itemstack2.isEmpty())
            {
                this.handler.setStackInSlot(3,itemstack1.copy());
            }
            else if (itemstack2.getItem() == itemstack1.getItem())
            {
                itemstack2.grow(itemstack1.getCount());
            }
            itemstack[0].shrink(1);
            itemstack[1].shrink(1);
        }
    }

    //定义燃料燃烧的时间
    public static int getItemBurnTime(ItemStack fuel)
    {
        if(fuel.isEmpty()) return 0;
        else
        {
            Item item = fuel.getItem();

//            if (item instanceof ItemBlock && Block.getBlockFromItem(item) != Blocks.AIR)
//            {
//                Block block = Block.getBlockFromItem(item);
//
//                if (block == Blocks.WOODEN_SLAB) return 150;
//                if (block.getDefaultState().getMaterial() == Material.WOOD) return 300;
//                if (block == Blocks.COAL_BLOCK) return 16000;
//            }
//
//            if (item instanceof ItemTool && "WOOD".equals(((ItemTool)item).getToolMaterialName())) return 200;
//            if (item instanceof ItemSword && "WOOD".equals(((ItemSword)item).getToolMaterialName())) return 200;
//            if (item instanceof ItemHoe && "WOOD".equals(((ItemHoe)item).getMaterialName())) return 200;
//            if (item == Items.STICK) return 100;
            //我们设置燃料可以为煤炭、岩浆,你可以添加其他的东西成为燃料
            if (item == Items.COAL) return 1600;
            if (item == Items.LAVA_BUCKET) return 20000;
//            if (item == Item.getItemFromBlock(Blocks.SAPLING)) return 100;
//            if (item == Items.BLAZE_ROD) return 2400;

            return GameRegistry.getFuelValue(fuel);
        }
    }
    public static boolean isItemFuel(ItemStack fuel)
    {
        return getItemBurnTime(fuel) > 0;
    }

    public boolean isUsableByPlayer(EntityPlayer player)
    {
        return this.world.getTileEntity(this.pos) != this ? false : player.getDistanceSq((double)this.pos.getX() + 0.5D, (double)this.pos.getY() + 0.5D, (double)this.pos.getZ() + 0.5D) <= 64.0D;
    }

    public int getField(int id)
    {
        switch(id)
        {
            case 0:
                return this.burnTime;
            case 1:
                return this.currentBurnTime;
            case 2:
                return this.cookTime;
            case 3:
                return this.totalCookTime;
            default:
                return 0;
        }
    }

    public void setField(int id, int value)
    {
        switch(id)
        {
            case 0:
                this.burnTime = value;
                break;
            case 1:
                this.currentBurnTime = value;
                break;
            case 2:
                this.cookTime = value;
                break;
            case 3:
                this.totalCookTime = value;
        }
    }

    public int getCookTime(ItemStack stack)
    {
        return 200;
    }
}

在tileEntity包中新建一个BlockVirusGenerator方块类用于实现方块实体:

BlockVirusGenerator.java

package com.joy187.rejoymod.blocks.tileEntity.virusGenerator;

import com.joy187.rejoymod.IdlFramework;
import com.joy187.rejoymod.blocks.BlockBase;
import com.joy187.rejoymod.blocks.ModBlocks;
import com.joy187.rejoymod.gui.ModGuiElementLoader;
import net.minecraft.block.BlockHorizontal;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyDirection;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.*;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.block.state.BlockStateContainer;

import java.util.Random;


public class BlockVirusGenerator extends BlockBase
{
    public static final PropertyDirection FACING = BlockHorizontal.FACING;
    //给机器增加一个燃烧的状态参数
    public static final PropertyBool BURNING = PropertyBool.create("burning");
    private static boolean keepInventory;

    public BlockVirusGenerator(String name)
    {
        super(name, Material.IRON);
        setSoundType(SoundType.METAL);
        this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH).withProperty(BURNING, false));
    }

    @Override
    public Item getItemDropped(IBlockState state, Random rand, int fortune)
    {
        return Item.getItemFromBlock(ModBlocks.VIRUS_GENERATOR);
    }

    @Override
    public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
    {
        return new ItemStack(ModBlocks.VIRUS_GENERATOR);
    }
    
    @Override
    public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
    {
        if(!worldIn.isRemote)
        {
            //点击方块显示我们的GUI
            playerIn.openGui(IdlFramework.instance, ModGuiElementLoader.GUI_VIRUS_GENERATOR, worldIn, pos.getX(), pos.getY(), pos.getZ());
        }

        return true;
    }

    @Override
    public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state)
    {
        if (!worldIn.isRemote)
        {
            IBlockState north = worldIn.getBlockState(pos.north());
            IBlockState south = worldIn.getBlockState(pos.south());
            IBlockState west = worldIn.getBlockState(pos.west());
            IBlockState east = worldIn.getBlockState(pos.east());
            EnumFacing face = (EnumFacing)state.getValue(FACING);

            if (face == EnumFacing.NORTH && north.isFullBlock() && !south.isFullBlock()) face = EnumFacing.SOUTH;
            else if (face == EnumFacing.SOUTH && south.isFullBlock() && !north.isFullBlock()) face = EnumFacing.NORTH;
            else if (face == EnumFacing.WEST && west.isFullBlock() && !east.isFullBlock()) face = EnumFacing.EAST;
            else if (face == EnumFacing.EAST && east.isFullBlock() && !west.isFullBlock()) face = EnumFacing.WEST;
            worldIn.setBlockState(pos, state.withProperty(FACING, face), 2);
        }
    }

    public static void setState(boolean active, World worldIn, BlockPos pos)
    {
        IBlockState state = worldIn.getBlockState(pos);
        TileEntity tileentity = worldIn.getTileEntity(pos);
        keepInventory = true;
        //如果机器在启动,就把机器设置为开启
        if(active) worldIn.setBlockState(pos, ModBlocks.VIRUS_GENERATOR.getDefaultState().withProperty(FACING, state.getValue(FACING)).withProperty(BURNING, true), 3);
        else worldIn.setBlockState(pos, ModBlocks.VIRUS_GENERATOR.getDefaultState().withProperty(FACING, state.getValue(FACING)).withProperty(BURNING, false), 3);

        keepInventory = false;
        if(tileentity != null)
        {
            tileentity.validate();
            worldIn.setTileEntity(pos, tileentity);
        }
    }

    @Override
    public boolean hasTileEntity(IBlockState state)
    {
        return true;
    }

    @Override
    public TileEntity createTileEntity(World world, IBlockState state)
    {
        return new TileEntityVirusGenerator();
    }

    @Override
    public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
    {
        return this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite());
    }

    @Override
    public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
    {
        worldIn.setBlockState(pos, this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite()), 2);
    }

    @Override
    public EnumBlockRenderType getRenderType(IBlockState state)
    {
        return EnumBlockRenderType.MODEL;
    }

    @Override
    public IBlockState withRotation(IBlockState state, Rotation rot)
    {
        return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING)));
    }

    @Override
    public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
    {
        return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING)));
    }

    @Override
    protected BlockStateContainer createBlockState()
    {
        return new BlockStateContainer(this, new IProperty[] {BURNING,FACING});
    }

    @Override
    public IBlockState getStateFromMeta(int meta)
    {
        EnumFacing facing = EnumFacing.getFront(meta);
        if(facing.getAxis() == EnumFacing.Axis.Y) facing = EnumFacing.NORTH;
        return this.getDefaultState().withProperty(FACING, facing);
    }

    @Override
    public int getMetaFromState(IBlockState state)
    {
        return ((EnumFacing)state.getValue(FACING)).getIndex();
    }


    //破坏机器,就把4个槽位的物品都弹出来
    public void breakBlock(World worldIn, BlockPos pos, IBlockState state)
    {
        TileEntityVirusGenerator tileentity = (TileEntityVirusGenerator)worldIn.getTileEntity(pos);
        if(!keepInventory)
        {
            worldIn.spawnEntity(new EntityItem(worldIn, pos.getX(), pos.getY(), pos.getZ(), tileentity.handler.getStackInSlot(0)));
            worldIn.spawnEntity(new EntityItem(worldIn, pos.getX(), pos.getY(), pos.getZ(), tileentity.handler.getStackInSlot(1)));
            worldIn.spawnEntity(new EntityItem(worldIn, pos.getX(), pos.getY(), pos.getZ(), tileentity.handler.getStackInSlot(2)));
            worldIn.spawnEntity(new EntityItem(worldIn, pos.getX(), pos.getY(), pos.getZ(), tileentity.handler.getStackInSlot(3)));
        }
        tileentity.setField(0,0);
        tileentity.setField(1,0);
        tileentity.setField(2,0);
        tileentity.setField(3,200);
        super.breakBlock(worldIn, pos, state);
    }
}

在tileEntity包中新建一个TileEntityHandler类将我们所有的方块机器进行注册:

TileEntityHandler.java


import com.joy187.rejoymod.blocks.tileEntity.virusGenerator.TileEntityVirusGenerator;
import com.joy187.rejoymod.util.Reference;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.registry.GameRegistry;

public class TileEntityHandler
{
    public static void registerTileEntities()
    {
        //GameRegistry.registerTileEntity(TileEntityCopperChest.class, new ResourceLocation(Reference.MODID + ":copper_chest"));
        GameRegistry.registerTileEntity(TileEntityVirusGenerator.class, new ResourceLocation(Reference.Mod_ID + ":virus_generator"));
    }
}

4.在gui包(没有就新建一个)中新建一个ModGuiElementLoader类:

ModGuiElementLoader.java

package com.joy187.rejoymod.gui;

import com.joy187.rejoymod.IdlFramework;
import com.joy187.rejoymod.blocks.tileEntity.virusGenerator.ContainerVirusGenerator;
import com.joy187.rejoymod.blocks.tileEntity.virusGenerator.GuiVirusGenerator;
import com.joy187.rejoymod.blocks.tileEntity.virusGenerator.TileEntityVirusGenerator;
import com.joy187.rejoymod.gui.expOne.ContainerDemo;
import com.joy187.rejoymod.gui.expOne.GuiContainerDemo;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.network.IGuiHandler;
import net.minecraftforge.fml.common.network.NetworkRegistry;

import javax.annotation.Nullable;


public class ModGuiElementLoader implements IGuiHandler {
    //给模组中所有机器的GUI依次编号
    public static final int GUI_VIRUS_GENERATOR = 1;
    public static final int GUI_DEMO = 2;
    public static final int GUI_RESEARCH = 3;

    public ModGuiElementLoader()
    {
        NetworkRegistry.INSTANCE.registerGuiHandler(IdlFramework.instance, this);
    }
    
    //sitch语句选择显示服务端的Container界面
    @Nullable
    @Override
    public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
        switch (ID)
        {
            case GUI_VIRUS_GENERATOR:
                return new ContainerVirusGenerator(player.inventory,(TileEntityVirusGenerator) world.getTileEntity(new BlockPos(x,y,z)));

            default:
                return null;
        }
    }
    //sitch语句选择显示客户端的Gui界面
    @Nullable
    @Override
    public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
        switch (ID)
        {
            case GUI_VIRUS_GENERATOR:
                return new GuiVirusGenerator(player.inventory,(TileEntityVirusGenerator) world.getTileEntity(new BlockPos(x,y,z)));

            default:
                return null;
        }
    }

}

5.给我们的机器添加其燃烧的配方,在tileEntity包中新建VirusGeneratorRecipes类:

VirusGeneratorRecipes.java

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import com.joy187.rejoymod.item.ModItems;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;

import java.util.Map;
import java.util.Map.Entry;
public class VirusGeneratorRecipes {
    private static final VirusGeneratorRecipes INSTANCE = new VirusGeneratorRecipes();
    private final Table smeltingList = HashBasedTable.create();
    private final Map experienceList = Maps.newHashMap();
    
    public static VirusGeneratorRecipes getInstance()
    {
        return INSTANCE;
    }

    private VirusGeneratorRecipes()
    {
        //我们的配方一共3个物品:2个原料+1个产物
        addGeneratorRecipe(new ItemStack(Items.ROTTEN_FLESH), new ItemStack(Items.GOLD_INGOT), new ItemStack(Items.NETHER_STAR), 5.0F);
        //addGeneratorRecipe(new ItemStack(Items.ROTTEN_FLESH), new ItemStack(Items.IRON_INGOT), new ItemStack(Items.DIAMOND), 5.0F);

    }


    public void addGeneratorRecipe(ItemStack input1, ItemStack input2, ItemStack result, float experience)
    {
        if(getSinteringResult(input1, input2) != ItemStack.EMPTY) return;
        this.smeltingList.put(input1, input2, result);
        this.experienceList.put(result, Float.valueOf(experience));
    }

    public ItemStack getSinteringResult(ItemStack input1, ItemStack input2)
    {
        for(Entry> entry : this.smeltingList.columnMap().entrySet())
        {
            if(this.compareItemStacks(input1, (ItemStack)entry.getKey()))
            {
                for(Entry ent : entry.getValue().entrySet())
                {
                    if(this.compareItemStacks(input2, (ItemStack)ent.getKey()))
                    {
                        return (ItemStack)ent.getValue();
                    }
                }
            }
        }
        return ItemStack.EMPTY;
    }

    private boolean compareItemStacks(ItemStack stack1, ItemStack stack2)
    {
        return stack2.getItem() == stack1.getItem() && (stack2.getMetadata() == 32767 || stack2.getMetadata() == stack1.getMetadata());
    }

    public Table getDualSmeltingList()
    {
        return this.smeltingList;
    }

    public float getGeneratorExperience(ItemStack stack)
    {
        for (Entry entry : this.experienceList.entrySet())
        {
            if(this.compareItemStacks(stack, (ItemStack)entry.getKey()))
            {
                return ((Float)entry.getValue()).floatValue();
            }
        }
        return 0.2F;
    }
}

5.在Main.java的Init()中添加ModGuiElementLoader的初始化:

Main.java

    @EventHandler
    public static void Init(FMLInitializationEvent event) {
        //ModRecipes.Init();
        //RegisterTileEntity();
        //initRegistries(event);
        //ModSpawn.registerSpawnList();
        //添加GUI初始化
        new ModGuiElementLoader();
        //NetworkHandler.init();

		//LogWarning("%s has finished its initializations", MODID);

	}

6.在ModBlocks中声明我们的方块:

ModBlocks.java

public static final Block VIRUS_GENERATOR = new BlockVirusGenerator("virus_generator");

在RegistryHandler.java中的onBlockRegister()中添加TileEntityHandler的注册语句:

	@SubscribeEvent
	public static void onBlockRegister(RegistryEvent.Register event) {
		TileEntityHandler.registerTileEntities();
	}

7.Java包的代码部分结束,找到resources包:

在en_us.lang中添加机器方块的名称:

container.virus_generator=Virus Analyser
tile.virus_generator.name=Virus Analyser

在blockstates包中新建virus_generator.json用于表示机器的不同形态下的模型

virus_generator.json

{
  "variants":
  {
    "burning=false,facing=north": { "model": "rejoymod:virus_generator" },
    "burning=false,facing=east": { "model": "rejoymod:virus_generator", "y": 90 },
    "burning=false,facing=south": { "model": "rejoymod:virus_generator", "y": 180 },
    "burning=false,facing=west": { "model": "rejoymod:virus_generator", "y": 270 },
    "burning=true,facing=north": { "model": "rejoymod:virus_generator_li" },
    "burning=true,facing=east": { "model": "rejoymod:virus_generator_li", "y": 90 },
    "burning=true,facing=south": { "model": "rejoymod:virus_generator_li", "y": 180 },
    "burning=true,facing=west": { "model": "rejoymod:virus_generator_li", "y":270  }
  }
}

在models/block包中新建virus_generator.json,显示机器的模型贴图地址

virus_generator.json

{
  "parent": "block/orientable",
  "textures": {
    "top": "rejoymod:blocks/sintering_furnace_side",
    "front": "rejoymod:blocks/sintering_furnace_front_off",
    "side": "rejoymod:blocks/sintering_furnace_side"
  }
}

同时需要制作方块工作时的模型贴图文件:
virus_generator_li.json

{
  "parent": "block/orientable",
  "textures": {
    "top": "rejoymod:blocks/sintering_furnace_side",
    "front": "rejoymod:blocks/sintering_furnace_front_on",
    "side": "rejoymod:blocks/sintering_furnace_side"
  }
}

在models/item包中新建virus_generator.json,显示手拿机器的模型

virus_generator.json

{
  "parent": "rejoymod:block/virus_generator"
}

在textures/blocks包中添加我们机器的3个贴图(一个为机器四周贴图,一个为机器关闭时贴图,一个为机器运作贴图):

Minecraft 1.12.2模组开发(三十九) 反应器(TileEntity方块实体)_第5张图片

8.保存所有文件 -> 运行游戏

首先拿出我们的机器并放置下来,外观显示正常

Minecraft 1.12.2模组开发(三十九) 反应器(TileEntity方块实体)_第6张图片

第5步中我们的反应器的一个配方为燃料+腐肉+金锭 ->下界之星,我们分别把东西摆进机器:

Minecraft 1.12.2模组开发(三十九) 反应器(TileEntity方块实体)_第7张图片
的确可以产出我们想要的东西,燃料和原料也都正常的消耗了。

同时我们发现在反应器工作时,机器同样显示为工作时的贴图:

Minecraft 1.12.2模组开发(三十九) 反应器(TileEntity方块实体)_第8张图片

本次用到的GUI界面(保存为.png格式,可根据PS软件进行修改):

Minecraft 1.12.2模组开发(三十九) 反应器(TileEntity方块实体)_第9张图片

你可能感兴趣的:(我的世界,minecraft,java)