Пакетная система и проблема с ней

Версия Minecraft
1.7.10

deleted.user

Мошенник
321
43
Привет всем. Начал делать пакетную систему, вроде бы все хорошо, но вот запара - просит повсюду метод onMessage(REQ, side). Хотя по идее не должен, если я ничего не упустил. Вот пара классов, собственно:

Java:
public abstract class AbstractMessage implements IMessage, IMessageHandler {

   protected abstract void read(PacketBuffer var1) throws IOException;

   protected abstract void write(PacketBuffer var1) throws IOException;

   public abstract void process(EntityPlayer var1, Side var2);

   protected boolean isValidOnSide(Side side) {
      return true;
   }

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

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

   public final IMessage onMessage(AbstractMessage msg, MessageContext ctx) {
      if(!msg.isValidOnSide(ctx.side)) {
         throw new RuntimeException("Invalid side " + ctx.side.name() + " for " + msg.getClass().getSimpleName());
      } else {
         msg.process(ModMain.proxy.getPlayerEntity(ctx), ctx.side);
         return null;
      }
   }

   public abstract static class AbstractClientMessage extends AbstractMessage {

      protected final boolean isValidOnSide(Side side) {
         return side.isClient();
      }
   }

   public abstract static class AbstractServerMessage extends AbstractMessage {

      protected final boolean isValidOnSide(Side side) {
         return side.isServer();
      }
   }
}

И код пакета:

Java:
public class OpenGuiMessage extends AbstractMessage.AbstractServerMessage {

   private int id;


   public OpenGuiMessage() {}

   public OpenGuiMessage(int id) {
      this.id = id;
   }

   protected void read(PacketBuffer buffer) {
      this.id = buffer.readInt();
   }

   protected void write(PacketBuffer buffer) {
      buffer.writeInt(this.id);
   }

   @Override
   public void process(EntityPlayer player, Side side) {
      player.openGui(ModMain.mod, this.id, player.worldObj, (int)player.posX, (int)player.posY, (int)player.posZ);
   }

Что я делаю не так и почему IDE просит добавить метод onMessage?
 
1,111
47
420
Потому что ты не переопределил этот метод в AbstractMessage. Абстрактный класс без реализованного абстрактного метода родителя требует реализации этого метода у потомков. А ещё я не вижу генериков в твоём AbstractMessage.
 
212
8
29
Java:
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);
        }
    }

    //=====================================================================//
    /*
     * Make the implementation final so child classes don't need to bother
     * with it, since the message class shouldn't have anything to do with
     * the handler. This is simply to avoid having to have:
     *
     * public static class Handler extends GenericMessageHandler<OpenGuiMessage> {}
     *
     * in every single message class for the sole purpose of registration.
     */
    @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(TutorialMain.proxy.getPlayerEntity(ctx), ctx.side);
        }
        return null;
    }

    /**
     * 1.8 ONLY: Ensures that the message is being handled on the main thread
     */
    private static final <T extends AbstractMessage<T>> void checkThreadAndEnqueue(final AbstractMessage<T> msg, final MessageContext ctx) {
        IThreadListener thread = TutorialMain.proxy.getThreadFromContext(ctx);
        // pretty much copied straight from vanilla code, see {@link PacketThreadUtil#checkThreadAndEnqueue}
        thread.addScheduledTask(new Runnable() {
            public void run() {
                msg.process(TutorialMain.proxy.getPlayerEntity(ctx), ctx.side);
            }
        });
    }

    /**
     * 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();
        }
    }
}
 
212
8
29
Еще в
Java:
ublic class PacketDispatcher
{
    // a simple counter will allow us to get rid of 'magic' numbers used during packet registration
    private static byte packetId = 0;

    /**
     * The SimpleNetworkWrapper instance is used both to register and send packets.
     * Since I will be adding wrapper methods, this field is private, but you should
     * make it public if you plan on using it directly.
     */
    private static final SimpleNetworkWrapper dispatcher = NetworkRegistry.INSTANCE.newSimpleChannel(TutorialMain.MODID);

    /**
     * Call this during pre-init or loading and register all of your packets (messages) here
     */
    public static final void registerPackets() {
        // Packets handled on CLIENT
        registerMessage(SyncPlayerPropsMessage.class);

        // Packets handled on SERVER
        registerMessage(OpenGuiMessage.class);

        // If you don't want to make a 'registerMessage' method, you can do it directly:
        //PacketDispatcher.dispatcher.registerMessage(SyncPlayerPropsMessage.class, SyncPlayerPropsMessage.class, packetId++, Side.CLIENT);
        //PacketDispatcher.dispatcher.registerMessage(OpenGuiMessage.class, OpenGuiMessage.class, packetId++, Side.SERVER);

        // The following two packets are not used in this demo, but have been used in my other mods
        // I include them here simply for the sake of demonstrating packets that can be sent to both sides

        // Bidirectional packets:
        registerMessage(PlaySoundPacket.class);
        registerMessage(AttackTimePacket.class);
    }

    /**
     * Registers an {@link AbstractMessage} to the appropriate side(s)
     */
    private static final <T extends AbstractMessage<T> & IMessageHandler<T, IMessage>> void registerMessage(Class<T> clazz) {
        // We can tell by the message class which side to register it on by using #isAssignableFrom (google it)

        // Also, one can see the convenience of using a static counter 'packetId' to keep
        // track of the current index, rather than hard-coding them all, plus it's one less
        // parameter to pass.
        if (AbstractMessage.AbstractClientMessage.class.isAssignableFrom(clazz)) {
            PacketDispatcher.dispatcher.registerMessage(clazz, clazz, packetId++, Side.CLIENT);
        } else if (AbstractMessage.AbstractServerMessage.class.isAssignableFrom(clazz)) {
            PacketDispatcher.dispatcher.registerMessage(clazz, clazz, packetId++, Side.SERVER);
        } else {
            // hopefully you didn't forget to extend the right class, or you will get registered on both sides
            PacketDispatcher.dispatcher.registerMessage(clazz, clazz, packetId, Side.CLIENT);
            PacketDispatcher.dispatcher.registerMessage(clazz, clazz, packetId++, Side.SERVER);
        }
    }

    //========================================================//
    // The following methods are the 'wrapper' methods; again,
    // this just makes sending a message slightly more compact
    // and is purely a matter of stylistic preference
    //========================================================//

    /**
     * Send this message to the specified player's client-side counterpart.
     * See {@link SimpleNetworkWrapper#sendTo(IMessage, EntityPlayerMP)}
     */
    public static final void sendTo(IMessage message, EntityPlayerMP player) {
        PacketDispatcher.dispatcher.sendTo(message, player);
    }

    /**
     * Send this message to everyone.
     * See {@link SimpleNetworkWrapper#sendToAll(IMessage)}
     */
    public static void sendToAll(IMessage message) {
        PacketDispatcher.dispatcher.sendToAll(message);
    }

    /**
     * Send this message to everyone within a certain range of a point.
     * See {@link SimpleNetworkWrapper#sendToAllAround(IMessage, NetworkRegistry.TargetPoint)}
     */
    public static final void sendToAllAround(IMessage message, NetworkRegistry.TargetPoint point) {
        PacketDispatcher.dispatcher.sendToAllAround(message, point);
    }

    /**
     * Sends a message to everyone within a certain range of the coordinates in the same dimension.
     * Shortcut to {@link SimpleNetworkWrapper#sendToAllAround(IMessage, NetworkRegistry.TargetPoint)}
     */
    public static final void sendToAllAround(IMessage message, int dimension, double x, double y, double z, double range) {
        PacketDispatcher.sendToAllAround(message, new NetworkRegistry.TargetPoint(dimension, x, y, z, range));
    }

    /**
     * Sends a message to everyone within a certain range of the player provided.
     * Shortcut to {@link SimpleNetworkWrapper#sendToAllAround(IMessage, NetworkRegistry.TargetPoint)}
     */
    public static final void sendToAllAround(IMessage message, EntityPlayer player, double range) {
        PacketDispatcher.sendToAllAround(message, player.worldObj.provider.getDimensionId(), player.posX, player.posY, player.posZ, range);
    }

    /**
     * Send this message to everyone within the supplied dimension.
     * See {@link SimpleNetworkWrapper#sendToDimension(IMessage, int)}
     */
    public static final void sendToDimension(IMessage message, int dimensionId) {
        PacketDispatcher.dispatcher.sendToDimension(message, dimensionId);
    }

    /**
     * Send this message to the server.
     * See {@link SimpleNetworkWrapper#sendToServer(IMessage)}
     */
    public static final void senToServer(IMessage message) {
        PacketDispatcher.dispatcher.sendToServer(message);
    }
}
 
Сверху