Не работает кастомный инвентарь

Версия Minecraft
1.7.10
Пакеты:
package net.maslenok.inventory.packets;

import java.io.IOException;

import com.google.common.base.Throwables;

import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
import cpw.mods.fml.relauncher.Side;
import io.netty.buffer.ByteBuf;
import net.minecraft.client.main.Main;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;

public abstract class AbstractMessage<T extends AbstractMessage<T>> implements IMessage, IMessageHandler <T, IMessage> {
/**
* Some PacketBuffer methods throw IOException - default handling propagates the exception.
* if an IOException is expected but should not be fatal, handle it within this method.
*/
protected abstract void read(PacketBuffer buffer) throws IOException;

/**
* Some PacketBuffer methods throw IOException - default handling propagates the exception.
* if an IOException is expected but should not be fatal, handle it within this method.
*/
protected abstract void write(PacketBuffer buffer) throws IOException;

/**
* Called on whichever side the message is received;
* for bidirectional packets, be sure to check side
* If {@link #requiresMainThread()} returns true, this method is guaranteed
* to be called on the main Minecraft thread for this side.
*/
public abstract void process(EntityPlayer player, Side side);

/**
* If message is sent to the wrong side, an exception will be thrown during handling
* @return True if the message is allowed to be handled on the given side
*/
protected boolean isValidOnSide(Side side) {
return true; // default allows handling on both sides, i.e. a bidirectional packet
}

/**
* Whether this message requires the main thread to be processed (i.e. it
* requires that the world, player, and other objects are in a valid state).
*/
protected boolean requiresMainThread() {
return true;
}

@Override
public void fromBytes(ByteBuf buffer) {
try {
read(new PacketBuffer(buffer));
} catch (IOException e) {
throw Throwables.propagate(e);
}
}

@Override
public void toBytes(ByteBuf buffer) {
try {
write(new PacketBuffer(buffer));
} catch (IOException e) {
throw Throwables.propagate(e);
}
}

@Override
public final IMessage onMessage(T msg, MessageContext ctx) {
if (!msg.isValidOnSide(ctx.side)) {
throw new RuntimeException("Invalid side " + ctx.side.name() + " for " + msg.getClass().getSimpleName());
} else if (msg.requiresMainThread()) {
//*checkThreadAndEnqueue(msg, ctx);
} else {
msg.process(net.maslenok.inventory.main.Main.proxy.getPlayerEntity(ctx), ctx.side);
}
return null;
}

/**
* Messages that can only be sent from the server to the client should use this class
*/
public static abstract class AbstractClientMessage<T extends AbstractMessage<T>> extends AbstractMessage<T> {
@Override
protected final boolean isValidOnSide(Side side) {
return side.isClient();
}
}

/**
* Messages that can only be sent from the client to the server should use this class
*/
public static abstract class AbstractServerMessage<T extends AbstractMessage<T>> extends AbstractMessage<T> {
@Override
protected final boolean isValidOnSide(Side side) {
return side.isServer();
}
}
}
package net.maslenok.inventory.packets;

import java.io.IOException;

import com.google.common.base.Throwables;

import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
import cpw.mods.fml.relauncher.Side;
import io.netty.buffer.ByteBuf;
import net.minecraft.client.main.Main;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;

public abstract class AbstractMessage<T extends AbstractMessage<T>> implements IMessage, IMessageHandler <T, IMessage> {
/**
* Some PacketBuffer methods throw IOException - default handling propagates the exception.
* if an IOException is expected but should not be fatal, handle it within this method.
*/
protected abstract void read(PacketBuffer buffer) throws IOException;

/**
* Some PacketBuffer methods throw IOException - default handling propagates the exception.
* if an IOException is expected but should not be fatal, handle it within this method.
*/
protected abstract void write(PacketBuffer buffer) throws IOException;

/**
* Called on whichever side the message is received;
* for bidirectional packets, be sure to check side
* If {@link #requiresMainThread()} returns true, this method is guaranteed
* to be called on the main Minecraft thread for this side.
*/
public abstract void process(EntityPlayer player, Side side);

/**
* If message is sent to the wrong side, an exception will be thrown during handling
* @return True if the message is allowed to be handled on the given side
*/
protected boolean isValidOnSide(Side side) {
return true; // default allows handling on both sides, i.e. a bidirectional packet
}

/**
* Whether this message requires the main thread to be processed (i.e. it
* requires that the world, player, and other objects are in a valid state).
*/
protected boolean requiresMainThread() {
return true;
}

@Override
public void fromBytes(ByteBuf buffer) {
try {
read(new PacketBuffer(buffer));
} catch (IOException e) {
throw Throwables.propagate(e);
}
}

@Override
public void toBytes(ByteBuf buffer) {
try {
write(new PacketBuffer(buffer));
} catch (IOException e) {
throw Throwables.propagate(e);
}
}

@Override
public final IMessage onMessage(T msg, MessageContext ctx) {
if (!msg.isValidOnSide(ctx.side)) {
throw new RuntimeException("Invalid side " + ctx.side.name() + " for " + msg.getClass().getSimpleName());
} else if (msg.requiresMainThread()) {
//*checkThreadAndEnqueue(msg, ctx);
} else {
msg.process(net.maslenok.inventory.main.Main.proxy.getPlayerEntity(ctx), ctx.side);
}
return null;
}

/**
* Messages that can only be sent from the server to the client should use this class
*/
public static abstract class AbstractClientMessage<T extends AbstractMessage<T>> extends AbstractMessage<T> {
@Override
protected final boolean isValidOnSide(Side side) {
return side.isClient();
}
}

/**
* Messages that can only be sent from the client to the server should use this class
*/
public static abstract class AbstractServerMessage<T extends AbstractMessage<T>> extends AbstractMessage<T> {
@Override
protected final boolean isValidOnSide(Side side) {
return side.isServer();
}
}
}
package net.maslenok.inventory.packets;

import java.io.IOException;

import com.google.common.base.Throwables;

import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
import cpw.mods.fml.relauncher.Side;
import io.netty.buffer.ByteBuf;
import net.minecraft.client.main.Main;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;

public abstract class AbstractMessage<T extends AbstractMessage<T>> implements IMessage, IMessageHandler <T, IMessage> {
/**
* Some PacketBuffer methods throw IOException - default handling propagates the exception.
* if an IOException is expected but should not be fatal, handle it within this method.
*/
protected abstract void read(PacketBuffer buffer) throws IOException;

/**
* Some PacketBuffer methods throw IOException - default handling propagates the exception.
* if an IOException is expected but should not be fatal, handle it within this method.
*/
protected abstract void write(PacketBuffer buffer) throws IOException;

/**
* Called on whichever side the message is received;
* for bidirectional packets, be sure to check side
* If {@link #requiresMainThread()} returns true, this method is guaranteed
* to be called on the main Minecraft thread for this side.
*/
public abstract void process(EntityPlayer player, Side side);

/**
* If message is sent to the wrong side, an exception will be thrown during handling
* @return True if the message is allowed to be handled on the given side
*/
protected boolean isValidOnSide(Side side) {
return true; // default allows handling on both sides, i.e. a bidirectional packet
}

/**
* Whether this message requires the main thread to be processed (i.e. it
* requires that the world, player, and other objects are in a valid state).
*/
protected boolean requiresMainThread() {
return true;
}

@Override
public void fromBytes(ByteBuf buffer) {
try {
read(new PacketBuffer(buffer));
} catch (IOException e) {
throw Throwables.propagate(e);
}
}

@Override
public void toBytes(ByteBuf buffer) {
try {
write(new PacketBuffer(buffer));
} catch (IOException e) {
throw Throwables.propagate(e);
}
}

@Override
public final IMessage onMessage(T msg, MessageContext ctx) {
if (!msg.isValidOnSide(ctx.side)) {
throw new RuntimeException("Invalid side " + ctx.side.name() + " for " + msg.getClass().getSimpleName());
} else if (msg.requiresMainThread()) {
//*checkThreadAndEnqueue(msg, ctx);
} else {
msg.process(net.maslenok.inventory.main.Main.proxy.getPlayerEntity(ctx), ctx.side);
}
return null;
}

/**
* Messages that can only be sent from the server to the client should use this class
*/
public static abstract class AbstractClientMessage<T extends AbstractMessage<T>> extends AbstractMessage<T> {
@Override
protected final boolean isValidOnSide(Side side) {
return side.isClient();
}
}

/**
* Messages that can only be sent from the client to the server should use this class
*/
public static abstract class AbstractServerMessage<T extends AbstractMessage<T>> extends AbstractMessage<T> {
@Override
protected final boolean isValidOnSide(Side side) {
return side.isServer();
}
}
}
package net.maslenok.inventory.packets;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import net.maslenok.inventory.main.Main;
import net.minecraft.entity.player.EntityPlayer;

public class OpenGuiPacket extends AbstractPacket {
// this will store the id of the gui to open
private int id;

// The basic, no-argument constructor MUST be included to use the new automated handling
public OpenGuiPacket() {}

// if there are any class fields, be sure to provide a constructor that allows
// for them to be initialized, and use that constructor when sending the packet
public OpenGuiPacket(int id) {
this.id = id;
}

@Override
public void encodeInto(ChannelHandlerContext ctx, ByteBuf buffer) {
// basic Input/Output operations, very much like DataOutputStream
buffer.writeInt(id);
}

@Override
public void decodeInto(ChannelHandlerContext ctx, ByteBuf buffer) {
// basic Input/Output operations, very much like DataInputStream
id = buffer.readInt();
}

@Override
public void handleClientSide(EntityPlayer player) {
// for opening a GUI, we don't need to do anything here
}

@Override
public void handleServerSide(EntityPlayer player) {
// because we sent the gui's id with the packet, we can handle all cases with one line:
player.openGui(Main.instance, id, player.worldObj, (int) player.posX, (int) player.posY, (int) player.posZ);
}
}
package net.maslenok.inventory.packets;

import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.IMessageHandler;
import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import cpw.mods.fml.relauncher.Side;
import net.minecraft.client.main.Main;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;

public class PacketDispatcher {
private static byte packetId = 0;

private static final SimpleNetworkWrapper dispatcher = NetworkRegistry.INSTANCE.newSimpleChannel(net.maslenok.inventory.main.Main.MODID);

public static void registerPackets() {
//* Client
PacketDispatcher.registerMessage(net.maslenok.inventory.packets.OpenGuiPacket.class, net.maslenok.inventory.packets.OpenGuiPacket.class, Side.CLIENT);


//* Server
PacketDispatcher.registerMessage(net.maslenok.inventory.packets.SyncPlayerPropsPacket.class, net.maslenok.inventory.packets.SyncPlayerPropsPacket.class, Side.SERVER);
}


@SuppressWarnings("unchecked")
private static void registerMessage(Class handlerClass, Class messageClass, Side side) {
PacketDispatcher.dispatcher.registerMessage(handlerClass, messageClass, packetId++, side);
}

//Wrapper methods
public static void sendTo(IMessage message, EntityPlayerMP player) {
PacketDispatcher.dispatcher.sendTo(message, player);
}

public static void sendToAll(IMessage message) {
PacketDispatcher.dispatcher.sendToAll(message);
}

public static void sendToAllAround(IMessage message, NetworkRegistry.TargetPoint point) {
PacketDispatcher.dispatcher.sendToAllAround(message, point);
}

public static void sendToAllAround(IMessage message, int dimension, double x, double y, double z, double range) {
PacketDispatcher.dispatcher.sendToAllAround(message, new NetworkRegistry.TargetPoint(dimension, x, y, z, range));
}

public static void sendToAllAround(IMessage message, EntityPlayer player, double range) {
PacketDispatcher.sendToAllAround(message, player.worldObj.provider.dimensionId, player.posX, player.posY, player.posZ, range);
}

public static void sendToDimension(IMessage message, int dimensionId) {
PacketDispatcher.dispatcher.sendToDimension(message, dimensionId);
}

public static void sendToServer(IMessage message) {
PacketDispatcher.dispatcher.sendToServer(message);
}
}
package net.maslenok.inventory.packets;

import java.util.*;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.INetHandler;
import net.minecraft.network.NetHandlerPlayServer;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.network.FMLEmbeddedChannel;
import cpw.mods.fml.common.network.FMLOutboundHandler;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

@ChannelHandler.Sharable
public class PacketPipeline extends MessageToMessageCodec<FMLProxyPacket, AbstractPacket>{

private EnumMap<Side, FMLEmbeddedChannel> channels;
private LinkedList<Class<? extends AbstractPacket>> packets = new LinkedList<Class<? extends AbstractPacket>>();
private boolean isPostInitialised = false;

public boolean registerPacket(Class<? extends AbstractPacket> clazz) {
if(packets.size() > 256){
return false;
}

if(packets.contains(clazz)){
return false;
}

if(isPostInitialised){
return false;
}
packets.add(clazz);
return true;
}

//Кодирование пакета, в том числе настройки дискриминатора.
@Override
protected void encode(ChannelHandlerContext ctx, AbstractPacket msg, List<Object> out) throws Exception {
ByteBuf buffer = Unpooled.buffer();
Class<? extends AbstractPacket> clazz = msg.getClass();
if (!packets.contains(msg.getClass())) {
throw new NullPointerException("No Packet Registered for: " + msg.getClass().getCanonicalName());
}
byte discriminator = (byte) this.packets.indexOf(clazz);
buffer.writeByte(discriminator);
msg.encodeInto(ctx, buffer);
FMLProxyPacket proxyPacket = new FMLProxyPacket(buffer.copy(), ctx.channel().attr(NetworkRegistry.FML_CHANNEL).get());
out.add(proxyPacket);
}

//Декодирования и обработка пакета
@Override
protected void decode(ChannelHandlerContext ctx, FMLProxyPacket msg, List<Object> out) throws Exception {
ByteBuf payload = msg.payload();
byte discriminator = payload.readByte();
Class<? extends AbstractPacket> clazz = this.packets.get(discriminator);
if (clazz == null) {
throw new NullPointerException("No packet registered for discriminator: " + discriminator);
}
AbstractPacket pkt = clazz.newInstance();
pkt.decodeInto(ctx, payload.slice());
EntityPlayer player;
switch(FMLCommonHandler.instance().getEffectiveSide()){
case CLIENT:
player = this.getClientPlayer();
pkt.handleClientSide(player);
break;
case SERVER:
INetHandler netHandler = ctx.channel().attr(NetworkRegistry.NET_HANDLER).get();
player = ((NetHandlerPlayServer) netHandler).playerEntity;
pkt.handleServerSide(player);
break;
default:
}
out.add(pkt);
}

public void initialise() {
channels = NetworkRegistry.INSTANCE.newChannel("InventoryPacket", this);
registerPackets();
}

public void registerPackets() {
registerPacket(OpenGuiPacket.class);
registerPacket(SyncPlayerPropsPacket.class);
}

public void postInitialise(){
if (isPostInitialised){
return;
}
isPostInitialised = true;
Collections.sort(packets, new Comparator<Class<? extends AbstractPacket>>(){
public int compare(Class<? extends AbstractPacket> clazz1, Class<? extends AbstractPacket> clazz2){
int com = String.CASE_INSENSITIVE_ORDER.compare(clazz1.getCanonicalName(), clazz2.getCanonicalName());
if (com == 0){
com = clazz1.getCanonicalName().compareTo(clazz2.getCanonicalName());
}
return com;
}
});
}

@SideOnly(Side.CLIENT)
private EntityPlayer getClientPlayer(){
return Minecraft.getMinecraft().thePlayer;
}

public void sendToAll(AbstractPacket message){
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALL);
channels.get(Side.SERVER).writeAndFlush(message);
}


public void sendTo(AbstractPacket message, EntityPlayerMP player){
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.PLAYER);
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(player);
channels.get(Side.SERVER).writeAndFlush(message);
}

public void sendToAllAround(AbstractPacket message, NetworkRegistry.TargetPoint point){
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALLAROUNDPOINT);
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(point);
channels.get(Side.SERVER).writeAndFlush(message);
}

public void sendToDimension(AbstractPacket message, int dimensionId){
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.DIMENSION);
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(dimensionId);
channels.get(Side.SERVER).writeAndFlush(message);
}

public void sendToServer(AbstractPacket message){
channels.get(Side.CLIENT).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TOSERVER);
channels.get(Side.CLIENT).writeAndFlush(message);
}
}
package net.maslenok.inventory.packets;

import cpw.mods.fml.common.network.ByteBufUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import net.maslenok.inventory.proxy.common.CommonProxy;
import net.minecraft.client.main.Main;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTTagCompound;

public class SyncPlayerPropsPacket extends AbstractPacket {
// Previously, we've been writing each field in our properties one at a time,
// but that is really annoying, and we've already done it in the save and load
// NBT methods anyway, so here's a slick way to efficiently send all of your
// extended data, and no matter how much you add or remove, you'll never have
// to change the packet / synchronization of your data.

// this will store our ExtendedPlayer data, allowing us to easily read and write
private NBTTagCompound data;

// The basic, no-argument constructor MUST be included to use the new automated handling
public SyncPlayerPropsPacket() {}

// We need to initialize our data, so provide a suitable constructor:
public SyncPlayerPropsPacket(EntityPlayer player) {
// create a new tag compound
data = new NBTTagCompound();
// and save our player's data into it
ExtendedPlayer.get(player).saveNBTData(data);
}

@Override
public void encodeInto(ChannelHandlerContext ctx, ByteBuf buffer) {
// ByteBufUtils provides a convenient method for writing the compound
ByteBufUtils.writeTag(buffer, data);
}

@Override
public void decodeInto(ChannelHandlerContext ctx, ByteBuf buffer) {
// luckily, ByteBufUtils provides an easy way to read the NBT
data = ByteBufUtils.readTag(buffer);
}

@Override
public void handleClientSide(EntityPlayer player) {
// now we can just load the NBTTagCompound data directly; one and done, folks
ExtendedPlayer.get(player).loadNBTData(data);
}

@Override
public void handleServerSide(EntityPlayer player) {
// we never send this packet to the server, so do nothing here
}
private static final String getSaveKey(EntityPlayer player) {
// no longer a username field, so use the command sender name instead:
return player.getCommandSenderName() + ":" + 1;
}

public static final void loadProxyData(EntityPlayer player) {
ExtendedPlayer playerData = ExtendedPlayer.get(player);
NBTTagCompound savedData = player.getEntityData();
if (savedData != null) { playerData.loadNBTData(savedData); }
net.maslenok.inventory.main.Main.packetPipeline.sendTo(new SyncPlayerPropsPacket(player), (EntityPlayerMP) player);
}
}

Сам инвентарь кастомный:
package net.maslenok.inventory.iinventory;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemStack;

public class ContainerCustomPlayer extends Container {
/** Avoid magic numbers! This will greatly reduce the chance of you making errors in 'transferStackInSlot' method */
private static final int ARMOR_START = InventoryCustomPlayer.INV_SIZE, ARMOR_END = ARMOR_START+3,
INV_START = ARMOR_END+1, INV_END = INV_START+26, HOTBAR_START = INV_END+1,
HOTBAR_END = HOTBAR_START+8;

public ContainerCustomPlayer(EntityPlayer player, InventoryPlayer inventoryPlayer, InventoryCustomPlayer inventoryCustom)
{
int i;

// Add CUSTOM slots - we'll just add two for now, both of the same type.
// Make a new Slot class for each different item type you want to add
this.addSlotToContainer(new SlotCustom(inventoryCustom, 0, 80, 8));
this.addSlotToContainer(new SlotCustom(inventoryCustom, 1, 80, 26));

// Add ARMOR slots; note you need to make a public version of SlotArmor
// just copy and paste the vanilla code into a new class and change what you need
for (i = 0; i < 4; ++i)
{
this.addSlotToContainer(new SlotArmor(player, inventoryPlayer, inventoryPlayer.getSizeInventory() - 1 - i, 8, 8 + i * 18,

i));
}

// Add vanilla PLAYER INVENTORY - just copied/pasted from vanilla classes
for (i = 0; i < 3; ++i)
{
for (int j = 0; j < 9; ++j)
{
this.addSlotToContainer(new Slot(inventoryPlayer, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
this.addSlotToContainer(new Slot(inventoryPlayer, j + i * 9 + 9, 8 + j * 18, 104 + i * 18));

}
}

// Add ACTION BAR - just copied/pasted from vanilla classes
for (i = 0; i < 9; ++i)
{
this.addSlotToContainer(new Slot(inventoryPlayer, i, 8 + i * 18, 142));
}
}

/**
* This should always return true, since custom inventory can be accessed from anywhere
*/
@Override
public boolean canInteractWith(EntityPlayer player)
{
return true;
}

/**
* Called when a player shift-clicks on a slot. You must override this or you will crash when someone does that.
* Basically the same as every other container I make, since I define the same constant indices for all of them
*/
public ItemStack transferStackInSlot(EntityPlayer player, int par2)
{
ItemStack itemstack = null;
Slot slot = (Slot) this.inventorySlots.get(par2);

if (slot != null && slot.getHasStack())
{
ItemStack itemstack1 = slot.getStack();
itemstack = itemstack1.copy();

// Either armor slot or custom item slot was clicked
if (par2 < INV_START)
{
// try to place in player inventory / action bar
if (!this.mergeItemStack(itemstack1, INV_START, HOTBAR_END + 1, true))
{
return null;
}

slot.onSlotChange(itemstack1, itemstack);
}
// Item is in inventory / hotbar, try to place either in custom or armor slots
else
{
// if item is our custom item
if (itemstack1.getItem() instanceof net.minecraft.item.ItemAxe)
{
if (!this.mergeItemStack(itemstack1, 0, InventoryCustomPlayer.INV_SIZE, false))
{
return null;
}
}
// if item is armor
else if (itemstack1.getItem() instanceof ItemArmor)
{
int type = ((ItemArmor) itemstack1.getItem()).armorType;
if (!this.mergeItemStack(itemstack1, ARMOR_START + type, ARMOR_START + type + 1, false))
{
return null;
}
}
// item in player's inventory, but not in action bar
else if (par2 >= INV_START && par2 < HOTBAR_START)
{
// place in action bar
if (!this.mergeItemStack(itemstack1, HOTBAR_START, HOTBAR_START + 1, false))
{
return null;
}
}
// item in action bar - place in player inventory
else if (par2 >= HOTBAR_START && par2 < HOTBAR_END + 1)
{
if (!this.mergeItemStack(itemstack1, INV_START, INV_END + 1, false))
{
return null;
}
}
}

if (itemstack1.stackSize == 0)
{
slot.putStack((ItemStack) null);
}
else
{
slot.onSlotChanged();
}

if (itemstack1.stackSize == itemstack.stackSize)
{
return null;
}

slot.onPickupFromSlot(player, itemstack1);
}

return itemstack;
}
}
package net.maslenok.inventory.iinventory;

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;

import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.util.ResourceLocation;

public class GuiCustomPlayerInventory extends GuiContainer {

/** x size of the inventory window in pixels. Defined as float, passed as int */
private float xSize_lo;

/** y size of the inventory window in pixels. Defined as float, passed as int. */
private float ySize_lo;

/** Normally I use '(ModInfo.MOD_ID, "textures/...")', but it can be done this way as well */
private static final ResourceLocation iconLocation = new ResourceLocation("tutorial:textures/gui/custom_inventory.png");

/** Could use IInventory type to be more generic, but this way will save an import... */
private final InventoryCustomPlayer inventory;

public GuiCustomPlayerInventory(EntityPlayer player, InventoryPlayer inventoryPlayer, InventoryCustomPlayer

inventoryCustom)
{
super(new ContainerCustomPlayer(player, inventoryPlayer, inventoryCustom));
this.inventory = inventoryCustom;
// if you need the player for something later on, store it in a local variable here as well
}

/**
* Draws the screen and all the components in it.
*/
public void drawScreen(int mouseX, int mouseY, float f)
{
super.drawScreen(mouseX, mouseY, f);
xSize_lo = mouseX;
ySize_lo = mouseY;
}

/**
* Draw the foreground layer for the GuiContainer (everything in front of the items)
*/
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY)
{
// This method will simply draw inventory names on the screen - you could do without it entirely
// if that's not important to you, since we are overriding the default inventory rather than
// creating a specific type of inventory

String s = this.inventory.hasCustomInventoryName() ? this.inventory.getInventoryName() : I18n.format(this.inventory.getInventoryName());
// with the name "Custom Inventory", the 'Cu' will be drawn in the first slot
this.fontRendererObj.drawString(s, this.xSize - this.mc.fontRenderer.getStringWidth(s), 12, 4210752);
// this just adds "Inventory" above the player's inventory below
this.fontRendererObj.drawString(I18n.format("container.inventory"), 80, this.ySize - 96, 4210752);
}

/**
* Draw the background layer for the GuiContainer (everything behind the items)
*/
protected void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY)
{
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
mc.getTextureManager().bindTexture(iconLocation);
drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize);
drawPlayerModel(guiLeft + 51, guiTop + 75, 30, guiLeft + 51 - xSize_lo, guiTop + 25 - ySize_lo, mc.thePlayer);
}

/**
* Copied straight out of vanilla - renders the player model on screen
*/
public static void drawPlayerModel(int x, int y, int scale, float yaw, float pitch, EntityLivingBase entity) {
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
GL11.glPushMatrix();
GL11.glTranslatef(x, y, 50.0F);
GL11.glScalef(-scale, scale, scale);
GL11.glRotatef(180.0F, 0.0F, 0.0F, 1.0F);
float f2 = entity.renderYawOffset;
float f3 = entity.rotationYaw;
float f4 = entity.rotationPitch;
float f5 = entity.prevRotationYawHead;
float f6 = entity.rotationYawHead;
GL11.glRotatef(135.0F, 0.0F, 1.0F, 0.0F);
RenderHelper.enableStandardItemLighting();
GL11.glRotatef(-135.0F, 0.0F, 1.0F, 0.0F);
GL11.glRotatef(-((float) Math.atan(pitch / 40.0F)) * 20.0F, 1.0F, 0.0F, 0.0F);
entity.renderYawOffset = (float) Math.atan(yaw / 40.0F) * 20.0F;
entity.rotationYaw = (float) Math.atan(yaw / 40.0F) * 40.0F;
entity.rotationPitch = -((float) Math.atan(pitch / 40.0F)) * 20.0F;
entity.rotationYawHead = entity.rotationYaw;
entity.prevRotationYawHead = entity.rotationYaw;
GL11.glTranslatef(0.0F, entity.yOffset, 0.0F);
RenderManager.instance.playerViewY = 180.0F;
RenderManager.instance.renderEntityWithPosYaw(entity, 0.0D, 0.0D, 0.0D, 0.0F, 1.0F);
entity.renderYawOffset = f2;
entity.rotationYaw = f3;
entity.rotationPitch = f4;
entity.prevRotationYawHead = f5;
entity.rotationYawHead = f6;
GL11.glPopMatrix();
RenderHelper.disableStandardItemLighting();
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
OpenGlHelper.setActiveTexture(OpenGlHelper.lightmapTexUnit);
GL11.glDisable(GL11.GL_TEXTURE_2D);
OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
}
}
package net.maslenok.inventory.iinventory;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;

public class InventoryCustomPlayer implements IInventory {
/** The name your custom inventory will display in the GUI, possibly just "Inventory" */
private final String name = "Custom Inventory";

/** The key used to store and retrieve the inventory from NBT */
private final String tagName = "CustomInvTag";

/** Define the inventory size here for easy reference */
// This is also the place to define which slot is which if you have different types,
// for example SLOT_SHIELD = 0, SLOT_AMULET = 1;
public static final int INV_SIZE = 2;

/** Inventory's size must be same as number of slots you add to the Container class */
private ItemStack[] inventory = new ItemStack[INV_SIZE];

public InventoryCustomPlayer()
{
// don't need anything here!
}

@Override
public int getSizeInventory()
{
return inventory.length;
}

@Override
public ItemStack getStackInSlot(int slot)
{
return inventory[slot];
}

@Override
public ItemStack decrStackSize(int slot, int amount)
{
ItemStack stack = getStackInSlot(slot);
if (stack != null)
{
if (stack.stackSize > amount)
{
stack = stack.splitStack(amount);
this.markDirty();
}
else
{
setInventorySlotContents(slot, null);
}
}
return stack;
}

@Override
public ItemStack getStackInSlotOnClosing(int slot)
{
ItemStack stack = getStackInSlot(slot);
setInventorySlotContents(slot, null);
return stack;
}

@Override
public void setInventorySlotContents(int slot, ItemStack itemstack)
{
this.inventory[slot] = itemstack;

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

this.markDirty();
}

@Override
public String getInventoryName()
{
return name;
}

@Override
public boolean hasCustomInventoryName()
{
return name.length() > 0;
}

/**
* Our custom slots are similar to armor - only one item per slot
*/
@Override
public int getInventoryStackLimit()
{
return 1;
}

@Override
public void markDirty()
{
for (int i = 0; i < getSizeInventory(); ++i)
{
if (getStackInSlot(i) != null && getStackInSlot(i).stackSize == 0) {
inventory = null;
}
}
}

@Override
public boolean isUseableByPlayer(EntityPlayer entityplayer)
{
return true;
}

@Override
public void openInventory() {}

@Override
public void closeInventory() {}

/**
* This method doesn't seem to do what it claims to do, as
* items can still be left-clicked and placed in the inventory
* even when this returns false
*/
@Override
public boolean isItemValidForSlot(int slot, ItemStack itemstack)
{
// If you have different kinds of slots, then check them here:
// if (slot == SLOT_SHIELD && itemstack.getItem() instanceof ItemShield) return true;

// For now, only ItemUseMana items can be stored in these slots
return itemstack.getItem() instanceof net.minecraft.item.ItemAxe;
}

public void writeToNBT(NBTTagCompound compound)
{
NBTTagList items = new NBTTagList();

for (int i = 0; i < getSizeInventory(); ++i)
{
if (getStackInSlot(i) != null)
{
NBTTagCompound item = new NBTTagCompound();
item.setByte("Slot", (byte) i);
getStackInSlot(i).writeToNBT(item);
items.appendTag(item);
}
}

// We're storing our items in a custom tag list using our 'tagName' from above
// to prevent potential conflicts
compound.setTag(tagName, items);
}

public void readFromNBT(NBTTagCompound compound) {
// now you must include the NBTBase type ID when getting the list; NBTTagCompound's ID is 10
NBTTagList items = compound.getTagList(tagName, compound.getId());
for (int i = 0; i < items.tagCount(); ++i) {
// tagAt(int) has changed to getCompoundTagAt(int)
NBTTagCompound item = items.getCompoundTagAt(i);
byte slot = item.getByte("Slot");
if (slot >= 0 && slot < getSizeInventory()) {
inventory[slot] = ItemStack.loadItemStackFromNBT(item);
}
}
}
}
package net.maslenok.inventory.iinventory;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;

public class InventoryCustomPlayer implements IInventory {
/** The name your custom inventory will display in the GUI, possibly just "Inventory" */
private final String name = "Custom Inventory";

/** The key used to store and retrieve the inventory from NBT */
private final String tagName = "CustomInvTag";

/** Define the inventory size here for easy reference */
// This is also the place to define which slot is which if you have different types,
// for example SLOT_SHIELD = 0, SLOT_AMULET = 1;
public static final int INV_SIZE = 2;

/** Inventory's size must be same as number of slots you add to the Container class */
private ItemStack[] inventory = new ItemStack[INV_SIZE];

public InventoryCustomPlayer()
{
// don't need anything here!
}

@Override
public int getSizeInventory()
{
return inventory.length;
}

@Override
public ItemStack getStackInSlot(int slot)
{
return inventory[slot];
}

@Override
public ItemStack decrStackSize(int slot, int amount)
{
ItemStack stack = getStackInSlot(slot);
if (stack != null)
{
if (stack.stackSize > amount)
{
stack = stack.splitStack(amount);
this.markDirty();
}
else
{
setInventorySlotContents(slot, null);
}
}
return stack;
}

@Override
public ItemStack getStackInSlotOnClosing(int slot)
{
ItemStack stack = getStackInSlot(slot);
setInventorySlotContents(slot, null);
return stack;
}

@Override
public void setInventorySlotContents(int slot, ItemStack itemstack)
{
this.inventory[slot] = itemstack;

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

this.markDirty();
}

@Override
public String getInventoryName()
{
return name;
}

@Override
public boolean hasCustomInventoryName()
{
return name.length() > 0;
}

/**
* Our custom slots are similar to armor - only one item per slot
*/
@Override
public int getInventoryStackLimit()
{
return 1;
}

@Override
public void markDirty()
{
for (int i = 0; i < getSizeInventory(); ++i)
{
if (getStackInSlot(i) != null && getStackInSlot(i).stackSize == 0) {
inventory = null;
}
}
}

@Override
public boolean isUseableByPlayer(EntityPlayer entityplayer)
{
return true;
}

@Override
public void openInventory() {}

@Override
public void closeInventory() {}

/**
* This method doesn't seem to do what it claims to do, as
* items can still be left-clicked and placed in the inventory
* even when this returns false
*/
@Override
public boolean isItemValidForSlot(int slot, ItemStack itemstack)
{
// If you have different kinds of slots, then check them here:
// if (slot == SLOT_SHIELD && itemstack.getItem() instanceof ItemShield) return true;

// For now, only ItemUseMana items can be stored in these slots
return itemstack.getItem() instanceof net.minecraft.item.ItemAxe;
}

public void writeToNBT(NBTTagCompound compound)
{
NBTTagList items = new NBTTagList();

for (int i = 0; i < getSizeInventory(); ++i)
{
if (getStackInSlot(i) != null)
{
NBTTagCompound item = new NBTTagCompound();
item.setByte("Slot", (byte) i);
getStackInSlot(i).writeToNBT(item);
items.appendTag(item);
}
}

// We're storing our items in a custom tag list using our 'tagName' from above
// to prevent potential conflicts
compound.setTag(tagName, items);
}

public void readFromNBT(NBTTagCompound compound) {
// now you must include the NBTBase type ID when getting the list; NBTTagCompound's ID is 10
NBTTagList items = compound.getTagList(tagName, compound.getId());
for (int i = 0; i < items.tagCount(); ++i) {
// tagAt(int) has changed to getCompoundTagAt(int)
NBTTagCompound item = items.getCompoundTagAt(i);
byte slot = item.getByte("Slot");
if (slot >= 0 && slot < getSizeInventory()) {
inventory[slot] = ItemStack.loadItemStackFromNBT(item);
}
}
}
}
package net.maslenok.inventory.iinventory;

import javax.swing.Icon;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.Item;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;

public class SlotArmor extends Slot {
/** The armor type that can be placed on that slot, it uses the same values of armorType field on ItemArmor. */
final int armorType;

/** The parent class of this slot, ContainerPlayer, SlotArmor is a Anon inner class. */
final EntityPlayer player;

public SlotArmor(EntityPlayer player, IInventory inventory, int slotIndex, int x, int y, int armorType)
{
super(inventory, slotIndex, x, y);
this.player = player;
this.armorType = armorType;
}

/**
* 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;
}

/**
* Check if the stack is a valid item for this slot. Always true beside for the armor slots.
*/
public boolean isItemValid(ItemStack itemstack)
{
Item item = (itemstack == null ? null : itemstack.getItem());
return item != null && item.isValidArmor(itemstack, armorType, player);
}

/**
* Returns the icon index on items.png that is used as background image of the slot.
*/
@SideOnly(Side.CLIENT)
public IIcon getBackgroundIconIndex()
{
return ItemArmor.func_94602_b(this.armorType);
}
}


package net.maslenok.inventory.iinventory;

import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;

public class SlotCustom extends Slot {
public SlotCustom(IInventory inventory, int slotIndex, int x, int y)
{
super(inventory, slotIndex, x, y);
}

/**
* Check if the stack is a valid item for this slot. Always true beside for the armor slots
* (and now also not always true for our custom inventory slots)
*/
@Override
public boolean isItemValid(ItemStack stack)
{
// We only want our custom item to be storable in this slot
return stack.getItem() instanceof net.minecraft.item.ItemAxe ;
}
}

Main:
package net.maslenok.inventory.main;

import net.maslenok.inventory.packets.OpenGuiPacket;
import net.maslenok.inventory.packets.PacketPipeline;
import net.maslenok.inventory.proxy.common.CommonProxy;
import net.minecraft.init.Blocks;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import cpw.mods.fml.relauncher.Side;

@Mod(modid = Main.MODID, name = Main.NAME, version = Main.VERSION)

public class Main
{
public static final String MODID = "Corspes";
public static final String NAME = "Corspes";
public static final String VERSION = "Beta";

@SidedProxy(clientSide="net.maslenok.inventory.proxy.client.ClientProxy", serverSide="net.maslenok.inventory.proxy.common.CommonProxy")
public static CommonProxy proxy;

@Instance("Main")
public static Main instance;

public static final PacketPipeline packetPipeline = new PacketPipeline();

@EventHandler
public void initialise(FMLInitializationEvent event){
packetPipeline.initialise();
packetPipeline.registerPacket(OpenGuiPacket.class); // Пакет открытия инвентаря.
}

@EventHandler
public void postInitialise(FMLPostInitializationEvent eventt){
packetPipeline.postInitialise();
}

@Mod.EventHandler
public void preInit(FMLPreInitializationEvent event)
{
proxy.preInit(event);
System.out.println("Hello World! I'm Micky Mouse, xa-xa :) (preinit)");
}

@Mod.EventHandler
public void init(FMLInitializationEvent event)
{
proxy.init(event);
System.out.println("Hello World! I'm Micky Mouse, xa-xa :) (init)");
}

@Mod.EventHandler
public void postInit(FMLPostInitializationEvent event)
{
proxy.postInit(event);
System.out.println("Hello World! I'm Micky Mouse, xa-xa :) (postinit)");
}
}

Proxys:
package net.maslenok.inventory.proxy.client;

import org.lwjgl.input.Keyboard;

import cpw.mods.fml.client.registry.ClientRegistry;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
import net.maslenok.inventory.iinventory.KeyHandler;
import net.maslenok.inventory.proxy.common.CommonProxy;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.common.MinecraftForge;

public class ClientProxy extends CommonProxy {

public void preInit(FMLPreInitializationEvent event)
{
super.preInit(event);
}

public void init(FMLInitializationEvent event)
{
super.init(event);
FMLCommonHandler.instance().bus().register(new KeyHandler());

}


public void postInit(FMLPostInitializationEvent event)
{
super.postInit(event);
}

public EntityPlayer getPlayerEntity(MessageContext ctx)
{
return ctx.side.isClient() ? Minecraft.getMinecraft().thePlayer : super.getPlayerEntity(ctx);
}
}
package net.maslenok.inventory.proxy.common;

import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
import net.minecraft.entity.player.EntityPlayer;

public class CommonProxy
{
public void preInit(FMLPreInitializationEvent event)
{
}

public void init(FMLInitializationEvent event)
{
}

public void postInit(FMLPostInitializationEvent event) {}

public EntityPlayer getPlayerEntity(MessageContext ctx)
{
return ctx.getServerHandler().playerEntity;
}
}
package net.maslenok.inventory.proxy.server;

import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import net.maslenok.inventory.proxy.common.CommonProxy;

public class ServerProxy extends CommonProxy {
public void preInit(FMLPreInitializationEvent event)
{
super.preInit(event);
}

public void init(FMLInitializationEvent event)
{
super.init(event);
}

public void postInit(FMLPostInitializationEvent event)
{
super.postInit(event);
}
}

Заранее спасибо.
Не могу понять почему не работает инвентарь.
Кто сможет помочь - буду благодарен.
 
Последнее редактирование:
161
12
90
Почему если я что то делаю, то стараюсь сделать там, погуглить на крайняк, потратить денёк-два и разобраться, но блин. Нет слов.

По теме: разберись хотя бы в том что ты кинул. И для кода как не странно придуманы блоки кода. Хотя может быть и в оригинале так же...🤔(про KeyHandler)
 

Eifel

Модератор
1,624
79
609
Чет не читабельно вообще все. Попробуй с вставкой кода... Если не открываеться, в лог что-то выдает? Уверен, что твои пакеты вообще работают? Уверен, что нажатие кнопки срабатыва? Попробуй поискать дебаггером проблему(если сложно, то старыми добрыми System.out). Я не смотрел все, но у тебя пакеты неверно зареганы, что попалось на глаза. Для OpenGuiMessage надо указать Side.SERVER, так как срабатывать это все будет на сервере, для пакета синхронищации, наоборот Side.CLIENT, т.к. ты отправляешь инфу на клиент и работа с ней происходит именно там.

upd. посмотрел другие классы и какой-то фарш непонятный, почитай про пакетную систему лучше еще гайды
 
Сверху