Новый инвентарь игрока

Версия Minecraft
1.7.10
101
0
Делал себе инвентарь по этому гайду: КЛИК
Сначала всё шло нормально, но потом я запутался в обновлении на 1.7.10, а именно в пакетах и их отправке, откуда и пошла проблема.
Игра запускается, одиночная игра тоже. Но когда нажимаю на кнопку открытия инвентаря, появляется окно отсоединения и я попадаю в главное в меню в "Сетевую игру" с этой ошибкой:

[13:26:51] [Server thread/INFO] [STDOUT/]: [ru.ohmit.rpg.util.ExtendedPlayer:loadNBTData:92]: [TUT PROPS] Mana from NBT: 50/50
[13:26:51] [Client thread/DEBUG] [FML/]: Overriding dimension: using 0
[13:26:59] [Server thread/ERROR] [FML/]: FMLIndexedMessageCodec exception caught
io.netty.handler.codec.DecoderException: java.lang.NullPointerException: Undefined message for discriminator 0 in channel OhmitRpg
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?]
    at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?]
    at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) [DefaultChannelHandlerContext.class:?]
    at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) [DefaultChannelHandlerContext.class:?]
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:?]
    at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) [EmbeddedChannel.class:?]
    at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?]
    at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
    at net.minecraft.network.NetworkSystem.networkTick(NetworkSystem.java:182) [NetworkSystem.class:?]
    at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:726) [MinecraftServer.class:?]
    at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:614) [MinecraftServer.class:?]
    at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:118) [IntegratedServer.class:?]
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:485) [MinecraftServer.class:?]
    at net.minecraft.server.MinecraftServer$2.run(MinecraftServer.java:752) [MinecraftServer$2.class:?]
Caused by: java.lang.NullPointerException: Undefined message for discriminator 0 in channel OhmitRpg
    at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:73) ~[FMLIndexedMessageToMessageCodec.class:?]
    at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17) ~[FMLIndexedMessageToMessageCodec.class:?]
    at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?]
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?]
    ... 13 more
[13:26:59] [Server thread/ERROR] [FML/]: There was a critical exception handling a packet on channel OhmitRpg
io.netty.handler.codec.DecoderException: java.lang.NullPointerException: Undefined message for discriminator 0 in channel OhmitRpg
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?]
    at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?]
    at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) ~[DefaultChannelHandlerContext.class:?]
    at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) ~[DefaultChannelHandlerContext.class:?]
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) ~[DefaultChannelPipeline.class:?]
    at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) ~[EmbeddedChannel.class:?]
    at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?]
    at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
    at net.minecraft.network.NetworkSystem.networkTick(NetworkSystem.java:182) [NetworkSystem.class:?]
    at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:726) [MinecraftServer.class:?]
    at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:614) [MinecraftServer.class:?]
    at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:118) [IntegratedServer.class:?]
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:485) [MinecraftServer.class:?]
    at net.minecraft.server.MinecraftServer$2.run(MinecraftServer.java:752) [MinecraftServer$2.class:?]
Caused by: java.lang.NullPointerException: Undefined message for discriminator 0 in channel OhmitRpg
    at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:73) ~[FMLIndexedMessageToMessageCodec.class:?]
    at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17) ~[FMLIndexedMessageToMessageCodec.class:?]
    at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?]
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?]
    ... 13 more
[13:26:59] [Server thread/ERROR] [FML/]: FMLIndexedMessageCodec exception caught
io.netty.handler.codec.DecoderException: java.lang.NullPointerException: Undefined message for discriminator 0 in channel OhmitRpg
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?]
    at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?]
    at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) [DefaultChannelHandlerContext.class:?]
    at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) [DefaultChannelHandlerContext.class:?]
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:?]
    at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) [EmbeddedChannel.class:?]
    at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?]
    at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
    at net.minecraft.network.NetworkSystem.networkTick(NetworkSystem.java:182) [NetworkSystem.class:?]
    at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:726) [MinecraftServer.class:?]
    at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:614) [MinecraftServer.class:?]
    at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:118) [IntegratedServer.class:?]
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:485) [MinecraftServer.class:?]
    at net.minecraft.server.MinecraftServer$2.run(MinecraftServer.java:752) [MinecraftServer$2.class:?]
Caused by: java.lang.NullPointerException: Undefined message for discriminator 0 in channel OhmitRpg
    at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:73) ~[FMLIndexedMessageToMessageCodec.class:?]
    at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17) ~[FMLIndexedMessageToMessageCodec.class:?]
    at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?]
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?]
    ... 13 more
[13:26:59] [Server thread/ERROR] [FML/]: There was a critical exception handling a packet on channel OhmitRpg
io.netty.handler.codec.DecoderException: java.lang.NullPointerException: Undefined message for discriminator 0 in channel OhmitRpg
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?]
    at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?]
    at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) ~[DefaultChannelHandlerContext.class:?]
    at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) ~[DefaultChannelHandlerContext.class:?]
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) ~[DefaultChannelPipeline.class:?]
    at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) ~[EmbeddedChannel.class:?]
    at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?]
    at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
    at net.minecraft.network.NetworkSystem.networkTick(NetworkSystem.java:182) [NetworkSystem.class:?]
    at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:726) [MinecraftServer.class:?]
    at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:614) [MinecraftServer.class:?]
    at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:118) [IntegratedServer.class:?]
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:485) [MinecraftServer.class:?]
    at net.minecraft.server.MinecraftServer$2.run(MinecraftServer.java:752) [MinecraftServer$2.class:?]
Caused by: java.lang.NullPointerException: Undefined message for discriminator 0 in channel OhmitRpg
    at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:73) ~[FMLIndexedMessageToMessageCodec.class:?]
    at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17) ~[FMLIndexedMessageToMessageCodec.class:?]
    at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?]
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?]
    ... 13 more
[13:26:59] [Server thread/TRACE] [mcp/mcp]: Sending event FMLServerStoppingEvent to mod mcp

Вот файлы, которые у меня наплодились в попытках исправить эту проблему. Я даже не знаю что скинуть надо, так что вот список  - если что-то нужно, скажите, я скину код этого класса.
thumb.png
 
Решение
Упаковываешь только id. Про все остальное забыл
Код:
@Override
public void fromBytes(ByteBuf buffer) {
// basic Input/Output operations, very much like DataInputStream
id = buffer.readInt();
}

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


Бесполезное действие

Код:
World world = DimensionManager.getWorld(message.dim);
 if (world == null)
    return null;
Тоже бесполезное

Код:
Entity ent = ctx.getServerHandler().playerEntity;//world.getEntityByID(message.playerid);
 if(!(ent instanceof EntityPlayer))
    return null;

ctx.getServerHandler().playerEntity, на сколько я помню, вернет EntityPlayerMP. И он никогда не будет null. Также...
101
0
Dahaka написал(а):
Конструктор по умолчанию не забыл в IMessage?
Код:
public class OpenGuiMessage implements IMessage {
// 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 OpenGuiMessage() {}

// 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 OpenGuiMessage(int id) {
this.id = id;
}
...
So on
Скинуть полный класс?
 
101
0
Dahaka написал(а):
А ты случаем не абстрактные классы регаешь в SimpleNetworkWrapper?

 
Код:
public static SimpleNetworkWrapper network;
    
    public static final PacketPipeline packetPipeline = new PacketPipeline(); 
    
    @SidedProxy(clientSide="ru.ohmit.rpg.ClientProxy", serverSide="ru.ohmit.rpg.ServerProxy")
    public static CommonProxy proxy;
    
    @EventHandler
    public void preInit(FMLPreInitializationEvent e) {
        proxy.preInit(e);
        network = NetworkRegistry.INSTANCE.newSimpleChannel(MODID);
        network.registerMessage(OpenGuiMessage.Handler.class, OpenGuiMessage.class, 0, Side.SERVER);
    }
 
101
0
Вот OpenGuiMessage.java
Код:
package ru.ohmit.rpg.packet;

import cpw.mods.fml.common.network.simpleimpl.IMessage;
import cpw.mods.fml.common.network.simpleimpl.MessageContext;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayer;
import ru.ohmit.rpg.OhmitRpg;


/**
* If you are going with the more simple route, the only difference is your inner handler class signature
* will look like this:
*
* public static class Handler implements IMessageHandler<OpenGuiMessage, IMessage>
*
* and the only method will be:
*
* public IMessage onMessage(OpenGuiMessage, MessageContext)
*
* Note that you can't immediately tell what side you are supposed to be on just from looking at the method,
* and you have to do some work to get the player if you want it. But we fixed all that xD
*/
public class OpenGuiMessage implements IMessage {
// 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 OpenGuiMessage() {}

// 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 OpenGuiMessage(int id) {
this.id = id;
}

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

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

public static class Handler extends AbstractServerMessageHandler<OpenGuiMessage> {
@Override
public IMessage handleServerMessage(EntityPlayer player, OpenGuiMessage message, 
MessageContext ctx) {
// because we sent the gui's id with the packet, we can handle all cases with one line:
player.openGui(OhmitRpg.instance, message.id, player.worldObj, (int) player.posX, (int) player.posY, (int) player.posZ);
return null;
}
}
}
 
101
0
Чуть-чуть поправил некоторые классы, вот новая ошибка:
[15:36:19] [Server thread/ERROR] [FML]: There was a critical exception handling a packet on channel OhmitRpg
io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?]
at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) ~[DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) ~[DefaultChannelHandlerContext.class:?]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) ~[DefaultChannelPipeline.class:?]
at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) ~[EmbeddedChannel.class:?]
at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?]
at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:241) [NetworkManager.class:?]
at net.minecraft.network.NetworkSystem.networkTick(NetworkSystem.java:182) [NetworkSystem.class:?]
at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:726) [MinecraftServer.class:?]
at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:614) [MinecraftServer.class:?]
at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:118) [IntegratedServer.class:?]
at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:485) [MinecraftServer.class:?]
at net.minecraft.server.MinecraftServer$2.run(MinecraftServer.java:752) [MinecraftServer$2.class:?]
Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.LinkedList.checkElementIndex(Unknown Source) ~[?:1.8.0_31]
at java.util.LinkedList.get(Unknown Source) ~[?:1.8.0_31]
at ru.ohmit.rpg.packet.PacketPipeline.decode(PacketPipeline.java:96) ~[PacketPipeline.class:?]
at ru.ohmit.rpg.packet.PacketPipeline.decode(PacketPipeline.java:1) ~[PacketPipeline.class:?]
at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?]
... 13 more

PacketPipeline.java

Код:
@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;

   /**
    * Register your packet with the pipeline. Discriminators are automatically set.
    *
    * @param clazz the class to register
    *
    * @return whether registration was successful. Failure may occur if 256 packets have been registered or if the registry already contains this packet
    */
   public boolean registerPacket(Class<? extends AbstractPacket> clazz) {
       if (this.packets.size() > 256) {
           // You should log here!!
           return false;
       }

       if (this.packets.contains(clazz)) {
           System.out.println("contains clazz");
           return false;
       }

       if (this.isPostInitialised) {
           // You should log here!!
           return false;
       }

       this.packets.add(clazz);
       return true;
   }
   
   /** Defining packet ids allow for subtypes of Packet250CustomPayload all on single channel */
   public static final byte EXTENDED_PROPERTIES = 1, OPEN_SERVER_GUI = 2;

   // In line encoding of the packet, including discriminator setting
   @Override
   protected void encode(ChannelHandlerContext ctx, AbstractPacket msg, List<Object> out) throws Exception {
       ByteBuf buffer = Unpooled.buffer();
       Class<? extends AbstractPacket> clazz = msg.getClass();
       if (!this.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);
   }

   // In line decoding and handling of the packet
   @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);
   }

   // Method to call from FMLInitializationEvent
   public void initialise() {
	// NOTE: Be sure to change the channel from "TUT" to whatever you are using!!!
	   this.channels = NetworkRegistry.INSTANCE.newChannel(OhmitRpg.MODID, this);
	   
   }

   // Method to call from FMLPostInitializationEvent
   // Ensures that packet discriminators are common between server and client by using logical sorting
   public void postInitialise() {
       if (this.isPostInitialised) {
           return;
       }

       this.isPostInitialised = true;
       Collections.sort(this.packets, new Comparator<Class<? extends AbstractPacket>>() {

           @Override
           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;
   }

   /**
    * Send this message to everyone.
    * <p/>
    * Adapted from CPW's code in cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper
    *
    * @param message The message to send
    */
   public void sendToAll(AbstractPacket message) {
       this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALL);
       this.channels.get(Side.SERVER).writeAndFlush(message);
   }

   /**
    * Send this message to the specified player.
    * <p/>
    * Adapted from CPW's code in cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper
    *
    * @param message The message to send
    * @param player  The player to send it to
    */
   public void sendTo(AbstractPacket message, EntityPlayerMP player) {
       this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.PLAYER);
       this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(player);
       this.channels.get(Side.SERVER).writeAndFlush(message);
   }

   /**
    * Send this message to everyone within a certain range of a point.
    * <p/>
    * Adapted from CPW's code in cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper
    *
    * @param message The message to send
    * @param point   The {@link cpw.mods.fml.common.network.NetworkRegistry.TargetPoint} around which to send
    */
   public void sendToAllAround(AbstractPacket message, NetworkRegistry.TargetPoint point) {
       this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALLAROUNDPOINT);
       this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(point);
       this.channels.get(Side.SERVER).writeAndFlush(message);
   }

   /**
    * Send this message to everyone within the supplied dimension.
    * <p/>
    * Adapted from CPW's code in cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper
    *
    * @param message     The message to send
    * @param dimensionId The dimension id to target
    */
   public void sendToDimension(AbstractPacket message, int dimensionId) {
       this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.DIMENSION);
       this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(dimensionId);
       this.channels.get(Side.SERVER).writeAndFlush(message);
   }

   /**
    * Send this message to the server.
    * <p/>
    * Adapted from CPW's code in cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper
    *
    * @param message The message to send
    */
   public void sendToServer(AbstractPacket message) {
       this.channels.get(Side.CLIENT).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TOSERVER);
       this.channels.get(Side.CLIENT).writeAndFlush(message);
   }
   
   

}

96 строка:
Код:
 Class<? extends AbstractPacket> clazz = this.packets.get(discriminator);
 
7,099
324
1,510
101
0
Так, ну я вроде понял что такое пакеты, зачем они, как и когда их отправлять, но одно мне не ясно. Зачем нужен IExtendedEntityProperties?

Я сейчас переделал код, но инвентарь почему-то не открывается.

Вот:
Главный класс
Код:
@Mod(name = OhmitRpg.NAME, modid = OhmitRpg.MODID, version = OhmitRpg.VERSION)
public class OhmitRpg
{
	
	@Instance("modid")
	public static OhmitRpg instance = new OhmitRpg();
	

    public static final String NAME = "Ohmit Rpg";
    public static final String MODID = "OhmitRpg";
    public static final String VERSION = "0.1";
    
    
    public static CreativeTabs tabName = new CreativeTabs("Rpg")
    {
    	public Item getTabIconItem()
    	{
    		return Items.arrow;
    	}
    };
    
    
    /** This is used to keep track of GUIs that we make*/
    private static int modGuiIndex = 0;
    
    
    /** Custom GUI indices: */
    public static final int GUI_CUSTOM_INV = modGuiIndex++;
    
    
    public static SimpleNetworkWrapper channel;
    
    public static Item ItemNecklake;
    
    
    @SidedProxy(clientSide="ru.ohmit.rpg.ClientProxy", serverSide="ru.ohmit.rpg.CommonProxy")
    public static CommonProxy proxy;
    
    @EventHandler
    public void preInit(FMLPreInitializationEvent e) {
    	
    	channel = NetworkRegistry.INSTANCE.newSimpleChannel(MODID);
        proxy.preInit(e);
        

    }

    @EventHandler
    public void init(FMLInitializationEvent e) {
        proxy.init(e);

        channel.registerMessage(OpenGuiMessage.HandlerClient.class, OpenGuiMessage.class, 0, Side.CLIENT);
        channel.registerMessage(OpenGuiMessage.HandlerServer.class, OpenGuiMessage.class, 1, Side.SERVER);
        channel.registerMessage(SyncPlayerPropsMessage.HandlerClient.class, SyncPlayerPropsMessage.class, 2, Side.CLIENT);
        channel.registerMessage(SyncPlayerPropsMessage.HandlerServer.class, SyncPlayerPropsMessage.class, 3, Side.SERVER);
        
     // the majority of events use the MinecraftForge event bus:
        MinecraftForge.EVENT_BUS.register(new OhmitEventHandler());
        
        NetworkRegistry.INSTANCE.registerGuiHandler(this, new CommonProxy());
        
    }

    @EventHandler
    public void postInit(FMLPostInitializationEvent e) {
        proxy.postInit(e);
        
    }
}

CommonProxy
Код:
public class CommonProxy implements IGuiHandler {

	/** Used to store IExtendedEntityProperties data temporarily between player death and respawn */
	private static final Map<String, NBTTagCompound> extendedEntityData = new HashMap<String, NBTTagCompound>();
	
	public EntityPlayer getPlayerEntity(MessageContext ctx) {
		 return ctx.getServerHandler().playerEntity;
		}
	
	@Override
	public Object getServerGuiElement(int guiId, EntityPlayer player, World world, int x, int y, int z)
	{
		if (guiId == OhmitRpg.GUI_CUSTOM_INV) {
			return new ContainerCustomPlayer(player, player.inventory, ExtendedPlayer.get(player).inventory);
		} else {
			return null;
		}
	}
	
	public World getClientWorld()
	{
		return null;
}

	@Override
	public Object getClientGuiElement(int guiId, EntityPlayer player, World world, int x, int y, int z)
	{
		if (guiId == OhmitRpg.GUI_CUSTOM_INV) {
			return new GuiCustomPlayerInventory(player, player.inventory, ExtendedPlayer.get(player).inventory);
		} else {
			return null;
		}
	}
	
	
    public void preInit(FMLPreInitializationEvent e) {

    }

    public void init(FMLInitializationEvent e) {

    }

    public void postInit(FMLPostInitializationEvent e) {

    }

    /**
    * Adds an entity's custom data to the map for temporary storage
    * @param compound An NBT Tag Compound that stores the IExtendedEntityProperties data only
    */
    public static void storeEntityData(String name, NBTTagCompound compound)
    {
    extendedEntityData.put(name, compound);
    }

    /**
    * Removes the compound from the map and returns the NBT tag stored for name or null if none exists
    */
    public static NBTTagCompound getEntityData(String name)
    {
    return extendedEntityData.remove(name);
    }
}


EventHandler
Код:
public class OhmitEventHandler {
	
	@SubscribeEvent
	public void onEntityConstructing(EntityConstructing event)
	{
	/*
	Be sure to check if the entity being constructed is the correct type for the extended properties you're about to add! The null check may not be necessary - I only use it to make sure properties are only registered once per entity
	*/
	if (event.entity instanceof EntityPlayer && ExtendedPlayer.get((EntityPlayer) event.entity) == null)
	// This is how extended properties are registered using our convenient method from earlier
	ExtendedPlayer.register((EntityPlayer) event.entity);
	// That will call the constructor as well as cause the init() method
	// to be called automatically

	// If you didn't make the two convenient methods from earlier, your code would be
	// much uglier:
	if (event.entity instanceof EntityPlayer && event.entity.getExtendedProperties(ExtendedPlayer.EXT_PROP_NAME) == null)
	event.entity.registerExtendedProperties(ExtendedPlayer.EXT_PROP_NAME, new ExtendedPlayer((EntityPlayer) event.entity));
	}
	
	@SubscribeEvent
	public void onOpenGui(GuiOpenEvent event)
	{
		if(event.gui instanceof GuiInventory)
		{
			event.setCanceled(true);
			EntityPlayer player = FMLClientHandler.instance().getClient().thePlayer;
			OhmitRpg.channel.sendToServer(new OpenGuiMessage(player, OhmitRpg.GUI_CUSTOM_INV));
		}
	}

}


OpenGuiMessage
Код:
public class OpenGuiMessage implements IMessage {
int dim;
int playerid;
int id;

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

 // 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 OpenGuiMessage(EntityPlayer player, int id)
	{
		this.dim = player.worldObj.provider.dimensionId;
		this.playerid = player.getEntityId();
		this.id = id;
}

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

 @Override
 public void toBytes(ByteBuf buffer) {
 // basic Input/Output operations, very much like DataOutputStream
 buffer.writeInt(id);
 }
 
 public static class HandlerClient implements IMessageHandler<OpenGuiMessage, IMessage>
	{
		@Override
		public IMessage onMessage(OpenGuiMessage message, MessageContext ctx)
		{
			Minecraft.getMinecraft().thePlayer.openGui(OhmitRpg.instance, 1, Minecraft.getMinecraft().thePlayer.worldObj, MathHelper.floor_double(Minecraft.getMinecraft().thePlayer.posX), MathHelper.floor_double(Minecraft.getMinecraft().thePlayer.posY), MathHelper.floor_double(Minecraft.getMinecraft().thePlayer.posZ));
			return null;
		}
	}
	public static class HandlerServer implements IMessageHandler<OpenGuiMessage, IMessage>
	{
		@Override
		public IMessage onMessage(OpenGuiMessage message, MessageContext ctx)
		{
			World world = DimensionManager.getWorld(message.dim);
			if (world == null)
				return null;
			Entity ent = ctx.getServerHandler().playerEntity;//world.getEntityByID(message.playerid);
			if(!(ent instanceof EntityPlayer))
				return null;
			EntityPlayer player = (EntityPlayer) ent;
//			PacketPipeline.INSTANCE.sendToAll(new PacketNBTSync(player));
			OhmitRpg.channel.sendToAll(new SyncPlayerPropsMessage(player));
//			PacketPipeline.INSTANCE.sendTo(new PacketOpenGui(player,message.guiid), (EntityPlayerMP) player);
			boolean hasServerGui = OhmitRpg.proxy.getServerGuiElement(message.id, player, world, (int)player.posX, (int)player.posY, (int)player.posZ)!=null;
			player.openGui(OhmitRpg.instance, 1, player.worldObj, MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY), MathHelper.floor_double(player.posZ));
			return hasServerGui?null: new OpenGuiMessage(player,message.id);
		}
}
}

IExtendedEntityProperties
Код:
public class ExtendedPlayer implements IExtendedEntityProperties
{
/*
Here I create a constant EXT_PROP_NAME for this class of properties. You need a unique name for every instance of IExtendedEntityProperties you make, and doing it at the top of each class as a constant makes
it very easy to organize and avoid typos. It's easiest to keep the same constant name in every class, as it will be distinguished by the class name: ExtendedPlayer.EXT_PROP_NAME vs. ExtendedEntity.EXT_PROP_NAME

Note that a single entity can have multiple extended properties, so each property should have a unique name. Try to come up with something more unique than the tutorial example.
*/
public final static String EXT_PROP_NAME = "Mana";

// I always include the entity to which the properties belong for easy access
// It's final because we won't be changing which player it is
private final EntityPlayer player;

// Declare other variables you want to add here

// We're adding mana to the player, so we'll need current and max mana
private int currentMana, maxMana;

/** Custom inventory slots will be stored here - be sure to save to NBT! */
public final InventoryCustomPlayer inventory = new InventoryCustomPlayer();

/*
The default constructor takes no arguments, but I put in the Entity so I can initialize the above variable 'player'

Also, it's best to initialize any other variables you may have added, just like in any constructor.
*/
public ExtendedPlayer(EntityPlayer player)
{
this.player = player;
// Start with max mana. Every player starts with the same amount.
this.currentMana = this.maxMana = 50;
}

/**
* Used to register these extended properties for the player during EntityConstructing event
* This method is for convenience only; it will make your code look nicer
*/
public static final void register(EntityPlayer player)
{
player.registerExtendedProperties(ExtendedPlayer.EXT_PROP_NAME, new ExtendedPlayer(player));
}

/**
* Returns ExtendedPlayer properties for player
* This method is for convenience only; it will make your code look nicer
*/
public static final ExtendedPlayer get(EntityPlayer player)
{
return (ExtendedPlayer) player.getExtendedProperties(EXT_PROP_NAME);
}

// Save any custom data that needs saving here
@Override
public void saveNBTData(NBTTagCompound compound)
{
// We need to create a new tag compound that will save everything for our Extended Properties
NBTTagCompound properties = new NBTTagCompound();

// We only have 2 variables currently; save them both to the new tag
properties.setInteger("CurrentMana", this.currentMana);
properties.setInteger("MaxMana", this.maxMana);

//Write custom inventory to NBT
this.inventory.writeToNBT(properties);

/*
Now add our custom tag to the player's tag with a unique name (our property's name). This will allow you to save multiple types of properties and distinguish between them. If you only have one type, it isn't as important, but it will still avoid conflicts between your tag names and vanilla tag names. For instance, if you add some "Items" tag, that will conflict with vanilla. Not good. So just use a unique tag name.
*/
compound.setTag(EXT_PROP_NAME, properties);
}

// Load whatever data you saved
@Override
public void loadNBTData(NBTTagCompound compound)
{
// Here we fetch the unique tag compound we set for this class of Extended Properties
NBTTagCompound properties = (NBTTagCompound) compound.getTag(EXT_PROP_NAME);
// Get our data from the custom tag compound
this.currentMana = properties.getInteger("CurrentMana");
this.maxMana = properties.getInteger("MaxMana");
// Just so you know it's working, add this line:
System.out.println("[TUT PROPS] Mana from NBT: " + this.currentMana + "/" + this.maxMana);


//Read custom inventory from NBT
this.inventory.readFromNBT(properties);

}


/*
I personally have yet to find a use for this method. If you know of any,
please let me know and I'll add it in!
*/
@Override
public void init(Entity entity, World world)
{
}

/*
That's it for the IExtendedEntityProperties methods, but we need to add a few of our own in order to interact with our new variables. For now, let's make one method to consume mana and one to replenish it.
*/

/**
* Returns true if the amount of mana was consumed or false
* if the player's current mana was insufficient
*/
public boolean consumeMana(int amount)
{
// Does the player have enough mana?
boolean sufficient = amount <= this.currentMana;
// Consume the amount anyway; if it's more than the player's current mana,
// mana will be set to 0
this.currentMana -= (amount < this.currentMana ? amount : this.currentMana);
// Return if the player had enough mana
return sufficient;
}

/**
* Simple method sets current mana to max mana
*/
public void replenishMana()
{
this.currentMana = this.maxMana;
}

public int getMaxMana() {
	return this.maxMana;
}

public float getCurrentMana() {
	return this.currentMana;
}

private static final String getSaveKey(EntityPlayer player) {
	// no longer a username field, so use the command sender name instead:
	return player.getCommandSenderName() + ":" + EXT_PROP_NAME;
}

public static final void loadProxyData(EntityPlayer player) {
	ExtendedPlayer playerData = ExtendedPlayer.get(player);
	NBTTagCompound savedData = CommonProxy.getEntityData(getSaveKey(player));
	if (savedData != null) { playerData.loadNBTData(savedData); }
	// we are replacing the entire sync() method with a single line; more on packets later
	// data can by synced just by sending the appropriate packet, as everything is handled internally by the packet class
	OhmitRpg.channel.sendTo(new SyncPlayerPropsMessage(player), (EntityPlayerMP) player);
}

}

SyncPlayerPropertiesMessage
Код:
public class SyncPlayerPropsMessage implements IMessage
// remember - the IMessageHandler will be implemented as a static inner class
{
 // 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 SyncPlayerPropsMessage() {}

 // We need to initialize our data, so provide a suitable constructor:
 public SyncPlayerPropsMessage(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 fromBytes(ByteBuf buffer) {
 // luckily, ByteBufUtils provides an easy way to read the NBT
 data = ByteBufUtils.readTag(buffer);
 }

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

 
 int dim;
	int playerid;
NBTTagCompound tag;
/**
 * Remember: this class MUST be static or you will crash
 *
 * Don't forget to add as well - it is required
 */

	public static class HandlerClient implements IMessageHandler<SyncPlayerPropsMessage, IMessage>
	{
		@Override
		public IMessage onMessage(SyncPlayerPropsMessage message, MessageContext ctx)
		{
			World world = OhmitRpg.proxy.getClientWorld();
			if (world == null)
				return null;
			Entity player = world.getEntityByID(message.playerid);
			if(!(player instanceof EntityPlayer))
				return null;
			if(message.tag == null)
			throw new RuntimeException("HEYO!");
			
			return null;
		}
	}
	public static class HandlerServer implements IMessageHandler<SyncPlayerPropsMessage, IMessage>
	{
		@Override
		public IMessage onMessage(SyncPlayerPropsMessage message, MessageContext ctx)
		{
			World world = DimensionManager.getWorld(message.dim);
			if (world == null)
				return null;
			Entity player = world.getEntityByID(message.playerid);
			if(!(player instanceof EntityPlayer))
				return null;
			OhmitRpg.channel.sendToAll(new SyncPlayerPropsMessage((EntityPlayer) player));
			return null;
		}
}
 
 // Note here that we don't (and can't) implement the handleServerMessage method
 // since we extended AbstractClientMessage. This is exactly what we want.
 }
 
Сверху